meaching learning
从接触机器学习到先在应该快有一个对月了, 可以说学习的过程十分痛苦, 但幸运的是我有的耐力还是很好的,并且有一颗平静的心,但慢慢的我对这个学科越来越兴趣了。每天起床都感觉自己好菜啊,成为支持我完成学习的动力。因为机器学习里面的包,函数都是由英文直译的或者是缩写,所以一些关键的名词我会用英文表示。
linearRegression
线性回归概念: 由若干输入(样本X), 对应的权重,和偏置向组成。
y^=θ0+θ1x1+θ2x2+⋯+θnxn \hat{y} = \theta_0 + \theta_1x_1 + \theta_2x_2+\cdots+\theta_nx_n y^=θ0+θ1x1+θ2x2+⋯+θnxn
我们做的是初始化线性回归模型根据预测输入与真实值之间的误差来参数W。
而在实际编程中一般用的是向量表示。
y^=hθ(X)=θT⋅X \hat{y} = h_\theta({X}) = \theta^T\cdot Xy^=hθ(X)=θT⋅X
线性回归的成本函数MSE(mean squared errror)
MSE(X,hθ)=1m∑i=1m(θ⋅X(i)−y(i))2 MSE(X, h_\theta) = \frac{1}{m}\sum_{i=1}^m(\theta \cdot X^{(i)} - y^{(i)})^2MSE(X,hθ)=m1i=1∑m(θ⋅X(i)−y(i))2
MSE(X, hθh_\thetahθ)是一个关于θ\thetaθ的函数。
可以利用极大释然估计求的函数的标准方程为:
θ^=(XT⋅X)−1⋅XT⋅y\hat{\theta} = (X^T \cdot X)^{-1} \cdot X^T \cdot yθ^=(XT⋅X)−1⋅XT⋅y
具体在代码中的实现方式:
import numpy as np
import matplotlib.pyplot as plt
X = np.np.random.randn(100, 1)
y = 4 + 3*X + np.random.randn(100, 1)#加入噪声否者样本将会是线性相关的
plt.scatter(X, y, 'r', label='point')#发出样本分布
plt.show()
计算θ\thetaθ
X_b = 2 * np.c_[np.ones(100, 1), X]
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
theta_best
#array([[3.95430313],
# [2.98117762]])
发出生成的模型:
x = np.linspace(1, 100, 100)
y = x*theta_best[0, 0] + theta_best[1, 0]
plt.plot(x, y, 'b')
plt.show()
sklearn的等效代码为:
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X, y)
lin_reg.intercept_, lin_reg.coef_
#array([[3.95430313],
# [2.98117762]])
比较一下,我们通过推导公式计算出来的值与通过sklearn计算出来的值是一样的,我们可以得出sklearn内部采用的算法也应该和我们写的一样。起码在(XT⋅X)−1(X^T \cdot X)^{-1}(XT⋅X)−1存在的情况下是这种情况。
linearRegression的推导过程
关键词:最大释然估计, 最小二乘法。
y(i)=θTx(i)+ξ(i)y^{(i)} = \theta^Tx^{(i)} + \xi^{(i)}y(i)=θTx(i)+ξ(i)
x(i)x^{(i)}x(i)表示第i个样本。
误差ξ(i)\xi^{(i)}ξ(i)独立同分布的,服从均值为0,方差为某定值σ2\sigma^2σ2的高斯分布(正太分布)。原因是:中心极限定理。
有:
p(σ(2))=12πσexp(−ξ(i)22σ2)p(y(i)∣x(i);θ)=12πσexp(−(y(i)−θTx(i))22σ2)L(θ)=∏i=1mp(y(i)∣x(i);θ)释然函数=∏i=1m12πσexp(−(y(i)−θTx(i))22σ2)
\begin{aligned}
p(\sigma^{(2)}) & = \frac{1}{\sqrt{2\pi}\sigma}\exp(-\frac{\xi^{(i)^2}}{2\sigma^2}) \\
p(y^{(i)}|x^{(i)}; \theta)& = \frac{1}{\sqrt{2\pi}\sigma}\exp(- \frac{(y^{(i)} - \theta^Tx^{(i)})^2}{2\sigma^2}) \\
L(\theta) & = \prod_{i=1}^{m}p(y^{(i)}|x^{(i)};\theta) &\text{释然函数}\\
& = \prod_{i=1}^{m} \frac{1}{\sqrt{2\pi}\sigma}\exp(- \frac{(y^{(i)} - \theta^Tx^{(i)})^2}{2\sigma^2}) \text{}
\end{aligned}
p(σ(2))p(y(i)∣x(i);θ)L(θ)=2πσ1exp(−2σ2ξ(i)2)=2πσ1exp(−2σ2(y(i)−θTx(i))2)=i=1∏mp(y(i)∣x(i);θ)=i=1∏m2πσ1exp(−2σ2(y(i)−θTx(i))2)释然函数
我们的目的是求取能使L(θ)值最大的θL(\theta)值最大的\thetaL(θ)值最大的θ。
乘法不好求求解,取对数后:
ψ(θ)=logL(θ)=log∏i=1m12πσexp(−(y(i)−θTx(i))22σ2) =∑i=1mlog12πσexp(−(y(i)−θTx(i))22σ2)=log12πσ−1σ2⋅12∑i=1m(y(i)−θTx(i))2
\begin{aligned}
\psi(\theta) &= \log{L(\theta)}\\
& = \log{\prod_{i=1}^{m} \frac{1}{\sqrt{2\pi}\sigma}\exp(- \frac{(y^{(i)} - \theta^Tx^{(i)})^2}{2\sigma^2}) \text{}} \\
\ & = \sum_{i=1}^{m}\log{\frac{1}{\sqrt{2\pi}\sigma}\exp(- \frac{(y^{(i)} - \theta^Tx^{(i)})^2}{2\sigma^2})} \\
& = \log{\frac{1}{\sqrt{2\pi}\sigma}} - \frac{1}{\sigma^2} \cdot \frac{1}{2} \sum_{i=1}^{m} (y^{(i)} - \theta^{T}x^{(i)})^2
\end{aligned}
ψ(θ) =logL(θ)=logi=1∏m2πσ1exp(−2σ2(y(i)−θTx(i))2)=i=1∑mlog2πσ1exp(−2σ2(y(i)−θTx(i))2)=log2πσ1−σ21⋅21i=1∑m(y(i)−θTx(i))2
J(θ)=12∑i=1m(h(θ)−y(i))2J(\theta) = \frac{1}{2} \sum_{i=1}^{m} (h(\theta) - y^{(i)})^2 J(θ)=21i=1∑m(h(θ)−y(i))2
θ取多少的时候ψ(θ)最大,即J(θ)最小\theta取多少的时候\psi(\theta)最大,即J(\theta)最小θ取多少的时候ψ(θ)最大,即J(θ)最小。
目标函数为:J(θ)=12∑i=1m(h(θ)−y(i))2=12∇θ(Xθ−y)T(Xθ−y)J(\theta) = \frac{1}{2} \sum_{i=1}^{m} (h(\theta) - y^{(i)})^2 = \frac{1}{2}\nabla_{\theta}(X\theta - y)^T(X
\theta-y)J(θ)=21i=1∑m(h(θ)−y(i))2=21∇θ(Xθ−y)T(Xθ−y)
梯度:
∇θJ(θ)=∇θ(12(Xθ−y)T(Xθ−y))=∇θ(12(θTXT−yT)(Xθ−y))=∇θ(12(θTXTXθ−θTXTy−yTXθ+yTy))=12(2XTXθ−XTy−(yTX)T)=XTXθ−XTy→(令驻点为)0
\begin{aligned}
\nabla_{\theta}J(\theta) & = \nabla_{\theta}(\frac{1}{2}(X\theta - y)^T(X
\theta-y)) = \nabla_{\theta}(\frac{1}{2}(\theta^TX^T - y^T)(X\theta-y)) \\
& = \nabla_{\theta}(\frac{1}{2}(\theta^TX^TX\theta - \theta^TX^Ty-y^TX\theta+y^Ty)) \\
& = \frac{1}{2}(2X^TX\theta - X^Ty-(y^TX)^T) = X^TX\theta - X^Ty \to(令驻点为) 0
\end{aligned}
∇θJ(θ)=∇θ(21(Xθ−y)T(Xθ−y))=∇θ(21(θTXT−yT)(Xθ−y))=∇θ(21(θTXTXθ−θTXTy−yTXθ+yTy))=21(2XTXθ−XTy−(yTX)T)=XTXθ−XTy→(令驻点为)0
需要说明的是:X的格式为: [x(1)Tx(2)Tx(3)T:x(n)T]
\left[
\begin{matrix}
x^{(1)^T} \\
x^{(2)^T} \\
x^{(3)^T} \\
: \\
x^{(n)^T}
\end{matrix}
\right]
⎣⎢⎢⎢⎢⎢⎡x(1)Tx(2)Tx(3)T:x(n)T⎦⎥⎥⎥⎥⎥⎤
解析式为:
θ^=(XT⋅X)−1⋅XT⋅y\hat{\theta} = (X^T \cdot X)^{-1} \cdot X^T \cdot yθ^=(XT⋅X)−1⋅XT⋅y
批量梯度下降
下面来说明当(XT⋅X)−1(X^T \cdot X)^{-1}(XT⋅X)−1不存的时候,我们将采用梯度下降法来求解参数。
- 初始化θ\thetaθ(随机初始化)
- 沿着负梯度方向迭代,更新后的θ\thetaθ是J(θ)J(\theta)J(θ)更小。
- θ=θ−α⋅∂J(θ)∂θGadient Descent,其中α为学习率,步长−−−(1)
\begin{aligned}
\theta &= \theta - \alpha\cdot\frac{\partial J(\theta)}{\partial \theta} &\text{Gadient Descent} , 其中\alpha 为学习率,步长 ---(1)
\end{aligned}
θ=θ−α⋅∂θ∂J(θ)Gadient Descent,其中α为学习率,步长−−−(1)
梯度方向为:
∂J(θ)∂θ=∂∂θ12(hθ(x)−y)2(2)=2⋅12(hθ(x)−y)⋅∂∂θj(hθ(x)−y)=(hθ(x)−y)⋅∂∂θj(∑i=0nθixi−y)=(hθ(x)−y)xj \begin{aligned} \frac{\partial J(\theta)}{\partial \theta} &= \frac{\partial}{\partial \theta}\frac{1}{2}(h_\theta(x) - y)^2 &\text{(2)}\\ & = 2\cdot\frac{1}{2}(h_\theta(x) -y)\cdot \frac{\partial}{\partial \theta_j}(h_\theta(x) - y) \\ & = (h_\theta(x) - y)\cdot \frac{\partial}{\partial \theta_j}(\sum_{i=0}^n\theta_ix_i-y) \\ & = (h_\theta(x) - y)x_j \end{aligned} ∂θ∂J(θ)=∂θ∂21(hθ(x)−y)2=2⋅21(hθ(x)−y)⋅∂θj∂(hθ(x)−y)=(hθ(x)−y)⋅∂θj∂(i=0∑nθixi−y)=(hθ(x)−y)xj(2)
结合公式(1)和(2)我们可以得到,一个迭代公式:
θj:=θj+α∑i=1m(y(i)−hθ(x(i)))xj(i)批量梯度下降 \theta_j : = \theta_j + \alpha \sum_{i=1}^m(y^{(i)} - h_\theta(x^{(i)}))x_j^{(i)} \text{批量梯度下降} θj:=θj+αi=1∑m(y(i)−hθ(x(i)))xj(i)批量梯度下降
所以成本函数的偏导数:
∂∂θjMSE(θ)=2m∑i=1m(θT⋅x(i)−y(i))xj(i) \frac{\partial}{\partial\theta_j}MSE(\theta) = \frac{2}{m}\sum_{i=1}^m(\theta^T \cdot x^{(i)} - y^{(i)})x_j^{(i)} ∂θj∂MSE(θ)=m2i=1∑m(θT⋅x(i)−y(i))xj(i)
当然这只是单单一个方向的偏导数,还需要求其他各个方向的变化。
可以发挥向量的优势:
∇θMSE(θ)=[∂∂θ0MSE(θ)∂∂θ1MSE(θ)∂∂θ2MSE(θ):∂∂θnMSE(θ)]=2mXT⋅(X⋅θ−y)\begin{aligned} \nabla_\theta MSE(\theta) = \left[ \begin{matrix} \frac{\partial}{\partial\theta_0}MSE(\theta) \\ \frac{\partial}{\partial\theta_1}MSE(\theta) \\ \frac{\partial}{\partial\theta_2}MSE(\theta) \\ : \\ \frac{\partial}{\partial\theta_n}MSE(\theta) \end{matrix} \right] = \frac{2}{m}X^T\cdot(X \cdot \theta - y) \end{aligned} ∇θMSE(θ)=⎣⎢⎢⎢⎢⎢⎡∂θ0∂MSE(θ)∂θ1∂MSE(θ)∂θ2∂MSE(θ):∂θn∂MSE(θ)⎦⎥⎥⎥⎥⎥⎤=m2XT⋅(X⋅θ−y)
所以最总的更新θ\thetaθ的得迭代公式为:
θ(nextstep)=θ−η∇θMSE(θ)\theta^{(next step)} = \theta-\eta\nabla_\theta MSE(\theta)θ(nextstep)=θ−η∇θMSE(θ)
利用前面的数据同样可以求的θ\thetaθ的值为:
eta = 0.1 #leaning rate
epochs = 1000
m = 1000
theta = np.random.randn(2, 1) #random initialation
for iteration in range(eppochs):
gradients = 2/m * X_b.T.dot(X_b.T.dot(theta) - y)
theta = theta - eta * gradints
#array([[4.13827648],
# [2.97768315]])
这里和面的结果几乎一样的,我这里差距有点大是因为该文章不是一天完成由于数据是随机数,重新运行notebook就会产生不一样的数据,一次运行的三次结果分别是:
#array([[4.13827657],
# [2.97768327]]) (公式法)
#(array([4.13827657]), array([[2.97768327]])) (sklearn-linearRegression)
#array([[4.13827648],
# [2.97768315]]) (批量梯度下降)
随机梯度下降
随机梯度下降的迭代公式为:
θj:=θj+α(y(i)−hθ(x(i)))xj(i)—随机梯度下降\theta_j : = \theta_j + \alpha (y^{(i)} - h_\theta(x^{(i)}))x_j^{(i)} \text{---随机梯度下降}θj:=θj+α(y(i)−hθ(x(i)))xj(i)—随机梯度下降
转化为向量形式为:
θ(nextstep)=θ−η⋅x(i).T(x(i)θ−yi)\theta^{(nextstep)} = \theta - \eta\cdot x^{(i)}.T(x^{(i)}\theta - y_i)θ(nextstep)=θ−η⋅x(i).T(x(i)θ−yi)
与批量不同的是随机梯度下降通过当个样本去更新权值,所以可以判定随机梯度下降是要比批量梯度下降快的。
代码实现形式为:
n_epochs = 50
t0, t1 = 5, 50
def learning_schedule(t):
return t0 / (t+t0)
theta = np.random.randn(2, 1) #random initialization
for epoch range(n_epochs):
for i in range(m):
random_index = np.random.randint(m)
xi = X_b[random_index:random_index+1]
yi = y[random_index:random_index+1]
gradients = 2 * xi.T.dot(xi.dot(theta) - yi)
eta = learning_schedule(epoch*m+i)
theta = theta - eta*gradients
theta
#array([[4.13064498],
# [2.98195638]])
比较两种梯度下降算法:
- 批量梯度下降:批量梯度下降的主要问题是他要用整个训练集来计算每一步的梯度,所以训练集很大时算法会特别慢。
- 随机梯度下降 :相对批量梯度下降算法速度会快很多,当成本函数非常多的不规则的时,随机梯度下降其实可以帮助算法跳出局部最小值,所以相对梯度下降,它对找到全局最小更有优势。
SGD(Stochastic gradient descent)在sklearn里面有现成的库可以使用。
from sklearn.linear_model import SGDRegressor
sgd_reg = SGDRegressor(n_iter=50, penalty=None, eta0=0.1)
sgd_reg.fit(X, y.ravel())
sgd_reg.intercept_, sgd_reg.coef_
#(array([3.86088849]), array([3.08750375]))
值得注意的是:随机梯度需要给出一些必要的参数n_iter,迭代次数eta0,以及学习率。
生成梯度下降参数路径:
线性回归算法比较
(m是训练实例的数量,n是特征数量)
算法 | m很大 | 是否支持核外 | n很大 | 超参数 | 是否需要缩放 | scikit-learn |
---|---|---|---|---|---|---|
标准方程 | 快 | 否 | 慢 | 0 | 否 | LinearRegression |
批量梯度下降 | 慢 | 否 | 快 | 2 | 是 | n/a |
随机梯度下降 | 快 | 是 | 快 | ≥2\ge2≥2 | 是 | SGDRegressior |
小批量梯度下降 | 快 | 是 | 快 | ≥2\ge2≥2 | 是 | n/a |
多项式回归
当数据更为复杂无法用线性模型来拟合数据的时候,可以用线性模型拟合非线性数据。将每个恩正的幂次方添加为一个新的特征。
利用scikit-Learn的PolynomialFeatures类来对训练数据进行装换。
from sklearn.preprocessing import PolynomialFeatures
poly_featuers = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly_featuers.fit_transform(X)
X_poly[:3]
#array([[ 0.09474328, 0.00897629],
# [-1.96174535, 3.84844482],
# [-1.32224302, 1.74832661],
通过线性模型来训练模型。
lin_reg = LinearRegression()
lin_reg.fit(X_poly, y)
lin_reg.intercept_, lin_reg.coef_
也可以采用更加高阶的所项式有可能会产生过拟合。那么我们要区分模型是拟合不足,还是过拟合呢。
学习曲线
通过观察学习曲线可以判断,模型的性能(拟合程度)。
这个曲线是模型在训练集和验证集上,关于‘训练集大小’的性能函数,要生成这个曲线,只需要在不同大小的训练集上多次训练模型即可。
def polting_learing_curves(model, x, y):
X_train, x_val, y_train, y_val = train_test_split(X ,y , test_size=0.2)
train_score, test_score = [], []
for i in range(1, len(X_train)):
model.fit(X_train[: i], y_train[:i])
prd_train = model.predict(X_train[:i])
prd_val = model.predict(x_val[:i])
mse = mean_squared_error(y_train[:i], prd_train)
mse1 = mean_squared_error(y_val[:i],prd_val )
train_score.append(np.sqrt(mse))
test_score.append(np.sqrt(mse1))
plt.ylim(0, 3)
plt.plot(train_score, 'r-+')
plt.plot(test_score, 'b-')
plt.savefig(r'C:\Users\lenovo\Desktop\02.png', dpi=400, bbox_inches='tight')
该二次项模型函数的学习曲线为:
分析该图像:因为两个模型均到达高地,非常接近,而且相当高,所以该图像是典型的拟合不足。
解决方案:真假训练的规模是于事无补的,需要更加复杂的模型,或者找出更好的特征。
选用复杂模型
from sklearn.pipeline import Pipeline
model = Pipeline((
('poly_features', PolynomialFeatures(degree = 10, include_bias=False)),
('sgd_reg', LinearRegression()),
))
学习曲线为:
可以观察到模型误差整体是较少的,但是验证误差与训练误差之间有一个较大的差别,这真实过拟合的表现的。
可以通过增加训练数据减少误差。