Coursera机器学习笔记1-单变量线性回归
一. 理论
1.1 训练集
假定给出一组数据:
Population | Profit |
---|---|
6.1101 | 17.592 |
5.5277 | 9.1302 |
8.5186 | 13.662 |
7.0032 | 11.854 |
左侧是x, 右侧是实际值 y
1.2 基本定义
1.2.1 假设函数
第一步先通过最简单的模型<一条直线>来拟合,这就是机器学习的’hello,world’,所以假设函数就是一条直线的方程式:
Hypothesis:
hθ(x)=θ0+θ1x
h
θ
(
x
)
=
θ
0
+
θ
1
x
* 敲黑板: * 上式虽然是一个关于x的方程,但是机器学习中认为x是己知的,我们实际要做的是找到拟合最好参数的
θ
θ
那么如何求解这个Hypothesis中的两个参数
θ
θ
呢? 这就引出了Cost Function(损失函数)
补充: 关于假设函数的向量表示
Hypothesis:
hθ(x)=θ0+θ1x
h
θ
(
x
)
=
θ
0
+
θ
1
x
可以写成这样的形式:即
hθ(x)=θ0x0+θ1x1
h
θ
(
x
)
=
θ
0
x
0
+
θ
1
x
1
,其中
x0≡1
x
0
≡
1
这样就可以把假设函数写成向量的形式: 即
hθ(x)=(θ0θ1)(x0x1)=θTX
h
θ
(
x
)
=
(
θ
0
θ
1
)
(
x
0
x
1
)
=
θ
T
X
,其中
x0≡1
x
0
≡
1
1.2.2 损失函数(平方误差函数)
预测值与误差项:
y(i)=θTxi+ϵ(i)
y
(
i
)
=
θ
T
x
i
+
ϵ
(
i
)
, 其中
ϵ(i)∼N(0,σ2)
ϵ
(
i
)
∼
N
(
0
,
σ
2
)
高斯分布,其中
μ=0
μ
=
0
高斯分布的公式是:
p(x)=12π√×σe−(x−μ)22σ2
p
(
x
)
=
1
2
π
×
σ
e
−
(
x
−
μ
)
2
2
σ
2
将误差项代入到高斯分布公式后得到:
p(ϵ(i))=12π√×σe−(ϵ(i))22σ2
p
(
ϵ
(
i
)
)
=
1
2
π
×
σ
e
−
(
ϵ
(
i
)
)
2
2
σ
2
将误差表达式代入得到:
p(y(i)|x(i);θ)=12π√×σe−(y(i)−θTx(i))22σ2
p
(
y
(
i
)
|
x
(
i
)
;
θ
)
=
1
2
π
×
σ
e
−
(
y
(
i
)
−
θ
T
x
(
i
)
)
2
2
σ
2
则
p(y1y2y3...yn)=p(y1)∗p(y2)∗p(y3)∗.....∗p(yn)
p
(
y
1
y
2
y
3
.
.
.
y
n
)
=
p
(
y
1
)
∗
p
(
y
2
)
∗
p
(
y
3
)
∗
.
.
.
.
.
∗
p
(
y
n
)
因为每个的概率都是独立的
记
L(θ)=p(y1y2y3...yn)
L
(
θ
)
=
p
(
y
1
y
2
y
3
.
.
.
y
n
)
, 则
L(θ)=∏i=1mp(y(i)|x(i);θ)=∏i=1m12π√×σe−(y(i)−θTx(i))22σ2
L
(
θ
)
=
∏
i
=
1
m
p
(
y
(
i
)
|
x
(
i
)
;
θ
)
=
∏
i
=
1
m
1
2
π
×
σ
e
−
(
y
(
i
)
−
θ
T
x
(
i
)
)
2
2
σ
2
高斯的对数似然与最小二乘法:
l(θ)=logL(θ)=log∏i=1m12π√×σe−(y(i)−θTx(i))22σ2
l
(
θ
)
=
log
L
(
θ
)
=
log
∏
i
=
1
m
1
2
π
×
σ
e
−
(
y
(
i
)
−
θ
T
x
(
i
)
)
2
2
σ
2
对数的乘积等于对数的加和:
logMN=logM+logN
log
M
N
=
log
M
+
log
N
, 则上式可变为:
=∑i=1mlog12π√×σe−(y(i)−θTx(i))22σ2
=
∑
i
=
1
m
log
1
2
π
×
σ
e
−
(
y
(
i
)
−
θ
T
x
(
i
)
)
2
2
σ
2
上式
log
log
的部分还是对数的乘积,再由对数的乘积等于对数的加和,可得:
=∑i=1mlog12π√×σ+∑i=1mloge−(y(i)−θTx(i))22σ2
=
∑
i
=
1
m
log
1
2
π
×
σ
+
∑
i
=
1
m
log
e
−
(
y
(
i
)
−
θ
T
x
(
i
)
)
2
2
σ
2
=mlog12π√×σ−1σ2⋅12∑i=1m(y(i)−θTx(i))2
=
m
log
1
2
π
×
σ
−
1
σ
2
⋅
1
2
∑
i
=
1
m
(
y
(
i
)
−
θ
T
x
(
i
)
)
2
分析一下上式: 因为
σ
σ
是一个定值,所以左边部分也是一个定值;要求
L(θ)
L
(
θ
)
的概率最大,右部分有一个负号
所以就是求:
J(θ)=12∑i=1m(y(i)−θTx(i))2
J
(
θ
)
=
1
2
∑
i
=
1
m
(
y
(
i
)
−
θ
T
x
(
i
)
)
2
的最小值,找到
θ
θ
使得
J(θ)
J
(
θ
)
最小
总结一下: 要使选择的
hθ(x)
h
θ
(
x
)
最接近y的值,那么问题就转化成为求
∑i=0n(hθ(x(i))−y(i))2
∑
i
=
0
n
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
的值最小的问题.
这里引入Cost Function记作
J(θ)
J
(
θ
)
:
J(θ)=12m∑i=1m(hθ(x(i))−y(i))2
J
(
θ
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
其中:
hθ(x)=θ0x0+θ1x1=θTX
h
θ
(
x
)
=
θ
0
x
0
+
θ
1
x
1
=
θ
T
X
1.3 梯度下降算法
有了损失函数是解决了what的问题,即什么样的参数
θ
θ
是拟合最好的参数,
那么下面就要解决how的问题,即如何找到拟合最好的
θ
θ
呢?
设置一个初始值,从初始值开始按照梯度下降的方法,一步步的迭代直至找到最小值,这个梯度下降的算法也就是不断求偏导的过程
所以
θ
θ
的更新公式就是:
θj:=θj−α∂∂θjJ(θ)
θ
j
:=
θ
j
−
α
∂
∂
θ
j
J
(
θ
)
只有这个更新公式还是不够,要真正进行编码还要继续推导才行
1.4 推导过程
θ
θ
的更新公式:
θj:=θj−α∂∂θjJ(θ)
θ
j
:=
θ
j
−
α
∂
∂
θ
j
J
(
θ
)
, 下面来看一下公式最后的偏导数部分是如何计算的
己知:
J(θ)=12m∑i=1m(hθ(x(i))−y(i))2(1)
(1)
J
(
θ
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
hθ(x)=θ0x0+θ1x1=θTX(2)
(2)
h
θ
(
x
)
=
θ
0
x
0
+
θ
1
x
1
=
θ
T
X
那么对公式
(1)
(
1
)
求偏导
∂∂θjJ(θ)=∂∂θj(12m∑i=1m(hθ(x(i))−y(i))2)=
∂
∂
θ
j
J
(
θ
)
=
∂
∂
θ
j
(
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
)
=
(12m∗2∑i=1m(hθ(x(i))−y(i)))∗∂∂θj(hθ(x(i))−y(i))
(
1
2
m
∗
2
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
)
∗
∂
∂
θ
j
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
将
(2)
(
2
)
的
hθ
h
θ
代入得到
∂∂θjJ(θ)=(12m∗2∑i=1m(hθ(x(i))−y(i)))∗∂∂θj(θ0x(i)0+θ1x(i)1−y(i))
∂
∂
θ
j
J
(
θ
)
=
(
1
2
m
∗
2
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
)
∗
∂
∂
θ
j
(
θ
0
x
0
(
i
)
+
θ
1
x
1
(
i
)
−
y
(
i
)
)
所以当
j=0
j
=
0
时
∂∂θ0J(θ)=1m∑i=1m(hθ(x(i))−y(i))∗x(i)0
∂
∂
θ
0
J
(
θ
)
=
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
∗
x
0
(
i
)
所以当
j=1
j
=
1
时
∂∂θ1J(θ)=1m∑i=1m(hθ(x(i))−y(i))∗x(i)1
∂
∂
θ
1
J
(
θ
)
=
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
∗
x
1
(
i
)
1.5 可编程的 θ θ 更新过程
θ
θ
的更新公式:
θj:=θj−α∂∂θjJ(θ)(3)
(3)
θ
j
:=
θ
j
−
α
∂
∂
θ
j
J
(
θ
)
同时有当
j=0
j
=
0
时
∂∂θ0J(θ)=1m∑i=1m(hθ(x(i))−y(i))∗x(i)0(4)
(4)
∂
∂
θ
0
J
(
θ
)
=
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
∗
x
0
(
i
)
由上述
(3)
(
3
)
与
(4)
(
4
)
可以得出: 当
j=0
j
=
0
时,
θ0
θ
0
的更新过程就是:
θ0:=θ0−α1m∑i=1m(hθ(x(i))−y(i))∗x(i)0(5)
(5)
θ
0
:=
θ
0
−
α
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
∗
x
0
(
i
)
二. 核心代码说明
2.1
# 批量梯度下降
def gradientDescent(X, y, theta, alpha, iters):
temp = np.matrix(np.zeros(theta.shape))
parameters = int(theta.ravel().shape[1])
# 下面这个for循环是对每组theta进行迭代
for i in range(iters):
error = (X * theta.T) - y
for j in range(parameters):
term = np.multiply(error, X[:, j])
temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))
theta = temp
return theta
其中X,y与
θ
θ
的值如下所示:iters 是迭代次数1000次
X=⎛⎝⎜⎜⎜1,6.11011,5.52771,8.51861,7.0032⎞⎠⎟⎟⎟4∗2y=⎛⎝⎜⎜⎜17.5929.130213.66211.854⎞⎠⎟⎟⎟4∗1θ=(0.00.0)2∗1
X
=
(
1
,
6.1101
1
,
5.5277
1
,
8.5186
1
,
7.0032
)
4
∗
2
y
=
(
17.592
9.1302
13.662
11.854
)
4
∗
1
θ
=
(
0.0
0.0
)
2
∗
1
2.1.1 逐行说明
error = (X * theta.T) - y
即求的: error=hθ(x(i))−y(i) e r r o r = h θ ( x ( i ) ) − y ( i ) 这是一个4*1的矩阵
term = np.multiply(error, X[:, j])
即求的: term=(hθ(x(i))−y(i))∗x(i)0 t e r m = ( h θ ( x ( i ) ) − y ( i ) ) ∗ x 0 ( i ) 这还是一个4*1的矩阵
temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))
np.sum(term)= ∑i=1m(hθ(x(i))−y(i))∗x(i)0 ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) ∗ x 0 ( i )
for j in range(parameters):
term = np.multiply(error, X[:, j])
temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))
不论是计算 θ0 θ 0 还是 θ1 θ 1 都需要计算 hθ(x(i))−y(i) h θ ( x ( i ) ) − y ( i ) ,所以这儿的error只需要计算一次,然后在for循环中使用其结果即可
三. 全部代码
3.1 全部代码
#coding:utf-8
__author__ = 'wangcong'
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 加载数据: 每行两个值,一个是x1,一个是Y
# 6.1101,17.592
# 5.5277,9.1302
# 8.5186,13.662
def loadDataSet():
# 将数据从文档中加载进内存
path = './ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
# 插入一列全为1的x0
data.insert(0, 'Ones', 1)
# 将数据分割为x 与 y, 其中x包含两项(x0,x1)
cols = data.shape[1]
x = data.iloc[:, 0:cols - 1] # x是所有行,去掉最后一列
y = data.iloc[:, cols - 1:cols] # y是所有行,最后一列
# 将x与y都转为matrix 方便计算
x = np.matrix(x.values)
y = np.matrix(y.values)
return data, x, y
# 批量梯度下降
def gradientDescent(X, y, theta, alpha, iters):
temp = np.matrix(np.zeros(theta.shape))
parameters = int(theta.ravel().shape[1])
for i in range(iters):
error = (X * theta.T) - y
for j in range(parameters):
term = np.multiply(error, X[:, j])
temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term))
theta = temp
return theta
# 画出结果
def plot_data(data, g):
x = np.linspace(data.Population.min(), data.Population.max(), 100)
f = g[0, 0] + (g[0, 1] * x)
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()
if __name__ == '__main__':
(data,x,y) = loadDataSet()
theta = np.matrix(np.array([0,0]))
print x.shape, y.shape, theta.shape, theta.T.shape
# 设置步长为0.01
alpha = 0.01
# 设置迭代次数为1000次
iters = 1000
theta = gradientDescent(x, y, theta, alpha, iters)
print theta
plot_data(data, theta)
注: 代码及数据文件ex1data1.txt己上传到github中
https://github.com/wangcong02345/machine
附录: 参考文献
吴恩达机器学习Coursera
<机器学习个人笔记完整版v4.51> by 黄海广 (大神啊!!!)
黄大神的1.linear_regreesion_v1.ipynb