2.单变量线性回归

2.1 模型表示

我们来看一个监督学习的例子,其采用的算法是线性回归算法。
在这里插入图片描述
这是一个俄勒冈波特兰市的房价,横轴是尺寸大小,纵轴是房价,我们通过算法能够预测不同的房子尺寸的房价,例如说房子尺寸是1250 f e e t 2 feet^2 feet2,通过线性回归曲线,大致预测出房价为220,000美元。

我们将使用一些标记作为训练集的参数。

在这里插入图片描述

标记含义
m训练集中实例数量
x输入变量(数量不定)
y输出变量
(x,y)训练集中的实例
( x ( i ) , y ( i ) ) (x^{(i)},y^{(i)}) (x(i),y(i))第i个实例
h(hypothesis)算法的函数

下图是预测(线性回归)的过程,h是从x到y的映射, h θ ( x ) = θ 0 x 0 + θ 1 x 1 + . . . + θ n x n h_ \theta(x)=\theta_0x_0+\theta_1x_1+...+\theta_nx_n hθ(x)=θ0x0+θ1x1+...+θnxn,由于讨论的是单变量线性回归,我们令 h θ ( x ) = θ 0 + θ 1 x h_ \theta(x)=\theta_0+\theta_1x hθ(x)=θ0+θ1x
在这里插入图片描述

2.2 代价函数(Cost Function)

为确定回归函数中的两个参数(原则是选择参数令假设函数最接近y),我们引入代价函数 J ( θ 0 , θ 1 ) J(\theta_0,\theta_1) J(θ0,θ1),目标是使得假设函数与实际输出的误差的平方最小,令 J ( θ 0 , θ 1 ) = 1 2 m ∑ i = 1 m ( h θ x i − y ( i ) ) 2 J(\theta_0,\theta_1)=\frac{1}{2m}\sum_{i=1}^{m}(h_\theta x^{i}-y^{(i)})^2 J(θ0,θ1)=2m1i=1m(hθxiy(i))2

建模误差:
在这里插入图片描述
根据绘制等高线:
在这里插入图片描述
寻找参数等价于寻找三维图像的最低点。

也可以把碗状图(convex function)降维成等高线(contour):
在这里插入图片描述
每个椭圆上的代价函数都是相同的,它的中心是代价函数值最小的点。

2.3 梯度下降法

梯度下降法是自动找到代价函数最小值的算法。

步骤:

  • 先假设 θ 0 , θ 1 \theta_0,\theta_1 θ0,θ1(一般假设为(0,0))
  • 调整参数减少代价函数直到终结于一个最小值

在这里插入图片描述
局限性:不用的起始点会得到不同的局部最优解。

梯度算法:
在这里插入图片描述
α \alpha α是学习率,决定了代价函数下降的“步伐”大小,太大会导致错过最小值。
在这里插入图片描述
α α θ x J ( θ x ) , x ∈ i n t [ 0 , 1 ] \frac{\alpha}{\alpha\theta_x}J(\theta_x) ,x\in int[0,1] αθxαJ(θx),xint[0,1]是偏导数
:=这个符号是赋值符号,我们要不断地修改参数,直到代价函数收敛。

分别对x=0,1求偏导:
α α θ 1 J ( θ 0 , θ 1 ) = ∑ i = 1 m 1 2 m ∗ 2 ∗ α α θ 1 ( θ 0 + θ 1 x i − y ( i ) ) ∗ x i \frac{\alpha}{\alpha_{\theta1}}J(\theta_0,\theta_1)=\sum_{i=1}^{m}\frac{1}{2m}*2*\frac{\alpha}{\alpha_{\theta 1}}(\theta_0+\theta_1x_i-y(i))*x^{i} αθ1αJ(θ0,θ1)=i=1m2m12αθ1α(θ0+θ1xiy(i))xi
h θ ( x i ) = θ 0 + θ 1 x i h_\theta(x^{i})=\theta_0+\theta_1x_i hθ(xi)=θ0+θ1xi

x=0偏导过程略

所以梯度迭代算法可改写为:
在这里插入图片描述

2.4 单变量线性回归习题

数据由吴恩达教授提供,关于population和profit的数据集。

# 单变量线性回归
import pandas as pd
import seaborn as sns
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
sns.set(context='notebook',palette='dark',style='whitegrid')
#读取数据 
df=pd.read_csv('ex1data1.txt',names=['population','profit'])
#注意fit_reg这个参数
sns.lmplot(x='population',y='profit',size=6,data=df, fit_reg=False)

# 用plt作图也可以
plt.figure(figsize=(15,10))
plt.plot(list(df.population),list(df.profit),'bo',markersize=6)

plt.xlabel('population')
plt.ylabel('profit')

在这里插入图片描述

# 共97个数据集
df.info()

在这里插入图片描述

# 读取特征、标签
def get_feature(df):
    #字典 A列均为1,长度是97
    A=pd.DataFrame({'A':np.ones(len(df))})
    data=pd.concat([A,df],axis=1)
    return data.iloc[:,:-1].to_numpy()


def get_label(df):
    return df.iloc[:,1].to_numpy()
    
# 计算代价函数
X=get_feature(df)
y=get_label(df)

#theta最开始设置(0,0)
theta=np.zeros(X.shape[1])
theta

#代价函数
def lr_cost(theta, X, y):
    m = X.shape[0]#m为样本数

    inner = X @ theta - y  # R(m*1),X @ theta等价于X.dot(theta)

    square_sum = inner.T @ inner
    cost = square_sum / (2 * m)

    return cost

#偏导数
def gradient(theta,X,y):
    m=X.shape[0]
    inner = X.T@(X@theta-y)
    return inner/m

#迭代,不能自动找到最小值,所以我设置两个代价函数的值小于10的(-9)此法则break
def gradient_iterator(X,y,epoch,theta,alpha=0.01):    
    theta_=theta.copy()
    loss=[lr_cost(theta,X,y)]
    for i in range(epoch):
        theta_=theta_-alpha*gradient(theta_,X,y)
        loss.append(lr_cost(theta_,X,y))
        if  np.abs(loss[-1] - loss[-2]) < 10 ** -9: 
            print(i)
            break
    return theta_,loss

#令epoch为5000,
#得到收敛的i是4286 
epoch=5000
final_theta,loss_data=gradient_iterator(X,y,epoch,theta)

得到 θ 0 和 θ 1 \theta_0和\theta_1 θ0θ1
在这里插入图片描述

#线性回归作图
theta_l=final_theta[0]
theta_r=final_theta[1]
l=(df.population)*theta_r+theta_l

plt.figure(figsize=(15,10))

plt.plot(list(df.population),list(df.profit),'bo',markersize=6)
plt.plot(list(df.population),list(l),color='blue',linewidth=2,label='prediction regression')
plt.xlabel('population')
plt.ylabel('profit')

在这里插入图片描述

#另一种线性回归算法,用tensorflow
def linear_regression(X_data, y_data, alpha, epoch, optimizer=tf.compat.v1.train.GradientDescentOptimizer):
      # placeholder for graph input
      #占位符,将数据传给计算图
    # (m,n)
    tf.compat.v1.disable_eager_execution()
    X = tf.compat.v1.placeholder(tf.float32, shape=X_data.shape)
    y = tf.compat.v1.placeholder(tf.float32, shape=y_data.shape)
    
     # construct the graph
        # 作用域‘linear_regression’
    with tf.compat.v1.variable_scope('linear-regression',reuse=tf.compat.v1.AUTO_REUSE):
        # W是n*1的矩阵,X_data.shape[i for i in range(2)]==(m,n),是theta
        W = tf.compat.v1.get_variable("weights",(X_data.shape[1], 1),initializer=tf.constant_initializer())  # n*1
        # y_pred是预测值,是(m,1)的矩阵,也就是说预测值与X_data的列的值相同
        y_pred = tf.compat.v1.matmul(X, W)  # m*n @ n*1 -> m*1
        #代价函数的矩阵J=1/2m *sum(y_pred-y)(y_pred-y)
        loss = 1 / (2 * len(X_data)) * tf.compat.v1.matmul((y_pred - y), (y_pred - y), transpose_a=True)  # (m*1).T @ m*1 = 1*1
   #alpha是学习率,控制梯度步伐的大小
    opt = optimizer(learning_rate=alpha)
    #线性回归问题等价于代价函数的最小值
    opt_operation = opt.minimize(loss)
    
     # run the session
    with tf.compat.v1.Session() as sess:
        sess.run(tf.compat.v1.global_variables_initializer())
        loss_data = []

        for i in range(epoch):
            #返回三个值,字典中的值来自X_data及y_data
            _, loss_val, W_val = sess.run([opt_operation, loss, W], feed_dict={X: X_data, y: y_data})
            loss_data.append(loss_val[0, 0])  # because every loss_val is 1*1 ndarray

            if len(loss_data) > 1 and np.abs(loss_data[-1] - loss_data[-2]) < 10 ** -9:  # early break when it's converged
                # print('Converged at epoch {}'.format(i))
                break
    tf.compat.v1.reset_default_graph()
    return {'loss': loss_data, 'parameters': W_val}  # just want to return in row vector format

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
函数tf.compat.v1.train.GradientDescentOptimizer可以自动找到梯度的最小值。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐