机器学习十天学习计划-2
线性回归
原理
有数据集{(x1, y1), (x2,y2),…,(xn, yn)}, 其中xi = (xi1, xi2,…,xid),y∈R;
其中,n表示样本的数量,d表示每个变量的维度。
可以用一个线性函数描述y与x之间的关系:
f
(
x
)
=
θ
0
+
θ
1
x
1
+
θ
2
x
2
+
.
.
.
.
.
.
+
θ
n
x
n
f(x) = \theta_{0} + \theta_{1}x_{1} + \theta_{2}x_{2} +......+\theta_{n}x_{n}
f(x)=θ0+θ1x1+θ2x2+......+θnxn
通过确定一组θ的值,来使得f(x)尽量的逼近y。
推导
均方误差是线性回归所用的损失函数,通过极大似然估计推导而来。
原理是通过假设目标值与变量之间的关系
y
i
=
θ
T
x
i
+
η
y^{i} = \theta^{T}x^{i} + \eta
yi=θTxi+η
其中η为随即噪音,假定其满足高斯分布,则可以得知关于θ的概率分布,建立θ的极大似然函数,通过选择θ,使得似然函数最大化,也就是使得
l
(
θ
)
=
1
/
2
∑
i
=
1
n
(
(
y
i
−
θ
T
x
i
)
2
l(\theta) = 1/2 \sum_{i=1}^{n}((y^{i}-\theta^{T}x^{i})^2
l(θ)=1/2i=1∑n((yi−θTxi)2最大化。具体的推导过程略。
把这个结果再除以样本数n即均方误差,因此用这个值作为代价函数来优化统计模型再统计学角度是合理的。
优化
梯度下降法
设定一个初始参数θ,通过不断迭代使得J(θ)最小,需要将J(θ)对θ求偏导。
这个方法中,参数在每一个数据点上都同时进行了移动,因此成为批梯度下降法。
相应的,如果每次只在针对一个样本更新参数,每次只针对一个数据点进行移动。即
θ
=
θ
+
α
(
y
i
−
f
θ
(
x
)
i
)
\theta = \theta + \alpha(y^{i} - f_{\theta}(x)^{i})
θ=θ+α(yi−fθ(x)i)成为随机梯度下降法。
数据量很大的时候,随机梯度下降法常优于批梯度下降。
代码:
#生成训练dataset
import numpy as np
np.random.seed(1234)
x = np.random.rand(500, 3)
y = x.dot(np.array([4.2, 5.7, 10.8]))
批量梯度下降法:
#批量梯度下降法求解参数
class LR_GD():
def __init__(self):
self.w = None
def fit(self, X, y, alpha=0.002, loss=1e-10):
y = y.reshape((-1, 1))
[m,d] = np.shape(X)
self.w = np.zeros((d,1))
tol = 1e5
theta = self.w
diff = np.dot(X, theta) - y
tol = (1/2)*np.dot(np.transpose(diff), diff)
while tol > loss:
gradient = np.dot(np.transpose(x), diff)
theta = theta - gradient*alpha
diff = np.dot(X, theta)-y
tol = (1/m)*np.dot(np.transpose(diff), diff)
tol = tol[0][0]
#print(tol)
return theta
def predict(self, X, weight):
y_pred = np.dot(X,weight)
return y_pred
#测试
if __name__ == "__main__":
lr_gd = LR_GD()
weight = lr_gd.fit(x, y)
print("估计的参数值为:%s"%(weight))
x_test = np.array([2,4,5]).reshape(1, -1)
print("预测值为:%s" %(lr_gd.predict(x_test, weight)))
运行结果:
估计的参数值为:[[ 4.20000516]
[ 5.70002061]
[10.7999735 ]]
预测值为:[[85.19996027]]
随机梯度下降法:
#随机梯度下降法求解
class LR_stoGD():
def __init__(self):
self.w = None
def fit(self, X, y, alpha=0.002, loss=1e-10):
y = y.reshape((-1,1))
[m,d] = np.shape(X)
self.w = np.zeros((1,d))
theta = self.w
for i in range(m):
diff = sum(np.dot((X[i,:]), np.transpose(theta))) - y[i,:]
gradient = X[i,:]*diff
theta = theta - alpha * gradient
#print(theta)
return theta
if __name__ == "__main__":
lr_stogd = LR_stoGD()
w = lr_stogd.fit(x, y)
print('估计的参数值是:%s'%(w))
运行结果:
估计的参数值是:[[3.58871918 4.00836808 4.17746749]]
由于只有500个样本,所以估计的参数值非常不准确。
每次仅使用一个样本点来更新梯度成为随机梯度上升算法,如果有数十亿的样本和成千上万的特征,批量梯度下降法的计算复杂度就太高了,才适用于随机梯度上升法。