机器学习第二章
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)=2m1∑i=1m(hθxi−y(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),x∈int[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=1m2m1∗2∗αθ1α(θ0+θ1xi−y(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可以自动找到梯度的最小值。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)