1.回归
首先我们可以理解什么是回归,假如我们有一系列x1,x2,x3,x4到xN并且对应y1,y2,y3,y4到yN。
在机器学习中,我们给定了一个x对应有一个y,这里有N个x对应N个y,这就是N组样本,从这N组样本中我们就可以进行一个建模,找出x和y的某种关系,从而对一个新给出的x值做y值的预测。
那么当这些y的值是一个连续的情况,比如1,2,3,4,5等等,我们称作回归。
当这些y的值是离散的,比如y是男女性别,取0或1,我们称作分类。
当然,回归这个字眼在所有人第一次接触字面时,会感觉和实际意义差距很远,而分类在解释上很容易行通,其实,我们可以这样解释回归:
任何事物的发展不是朝着极端走,双亲较矮,子代较高,但子代身高不会无限地增长,它往往会在一定范围内波动,并且会趋于一个稳定的值,就如同大部分事物在大量样本发生的情况下会趋于正态分布,这种现象我们可以称之为回归,也就是回归解释的是大量事物在一般情况下趋于最普遍的一种状态。
因此,当y值是连续的时候,我们就称作回归。
2.线性回归以及最小二乘法
y=ax+b是二维关系,推演至多维,也就是我们可以有很多特征共同决定y,于是就有如下图的关系,每一个特征都有一个θ参数,共同决定了预测的模型,我们将所有θ写在一个列向量中,并写为θ的转置乘对应的x并加和,我们最后需要知道的是θ,因为x和y是已给出的样本,其实就是对关于θ的函数求解
其实,我们得出了上图这个模型后,这是对于y的预测函数,也就是hθ(x) 和真实的y是有一定的误差,于是我们可以得到下图
我们假定样本都是独立的,那么样本的联合概率:
P(x1,x2,x3,…..,xN)=P(x1)P(x2)P(x3)…..P(xN)
并且样本也是同分布的,那么ε的形成是建模过程中未考虑的各种因素叠加而成,根据中心极限定理,这种最后的加和应该导向正态分布。
那么,既然是正态分布,就应该有N(μ,σ^2),这里的μ不为0,但是因为有截距θ0的存在,所以我们可以把模型进行移动使得μ变为0,所以可以认为μ的均值为0.
因为ε是符合正态分布的,所以我们根据正态分布函数可以得到下图:
又因为实际值y和预测值hθ(x)之间的关系,我们做一个替换,得到下图:
又因为我们已经假定这些样本是独立且同分布的,那么这些样本的联合概率就是所有样本概率的乘积,因此可以得到下图:
我们对这个式子两边取对数并拆分化简,得到下图:
我们化简到这一步的目的是什么呢?就是求θ在取何值的情况下,得到的对数的似然概率取最大,因为式子的前部分是定值,我们只需要使后部分最小即可,也就是使下图函数值最小:
到这里发现这个式子其实就是最小二乘法。
然而这一切都是建立在我们假定样本服从高斯分布的情况下反推得出的目标函数,如果样本服从拉普拉斯分布,那么目标函数得到的就是绝对值,而非平方。
3,最小二乘法的求解(θ的求解)
我们的预测值函数其实就是将N个M维样本与每一个θ相乘得到N个对应y值,所以说将其存入矩阵中也就是Xθ→y这样一个过程,所以可以把目标函数化成下图线性代数表达方式:
关于上图式子的化简,下面将推导一遍:
4.梯度下降算法
给定θ初值,然后不断地沿负梯度方向下降,时J(θ)越来越小,从而使得损失函数最小,求得此时的局部最优解θ,又因为对于线性回归的目标函数,它是一个二次的凸函数,这种局部最优θ可以被认为是全局最优解,从而可以得到最优的θ。
梯度下降算法有批量梯度下降和随机梯度下降,两者区别可以用下图表示:
批量下降是将所有样本目标函数求偏导加和,再下降
随机下降是来一个样本就求偏导,再下降。
关于∂J(θ)/∂θ,求解如下图:
其实还有一种折中的下降算法,但也归类在随机梯度下降中,不过它不是一个样本就下降梯度,而是若干样本的平均梯度进而下降。
5.关于正则的问题
我们在上面提到关于θ求解的问题,往往目标函数会因为θ过大而造成无法求得最优解的情况,这时候我们会在目标函数后面添加正则项,如下图:
正则项就是来抑制θ过大而无法求最优解的情况,因为θ一但很大,它的平方就会很大,那么目标函数无法取较小,这就说明这时候的θ不是最优解。
添加的正则项是θ的平方的加和称作L2正则,也叫岭(Ridge)回归,而另一种添加θ绝对值的加和称作L1正则,也叫Lasso。
往往用到的是L2正则,因为其可导,较容易求解,L1正则的求解过程会更为繁琐。
6.相关代码实现
这里给出的是广告数据来自
http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv
可以自行下载,简单的线性回归的一个例子
#!/usr/bin/python
# -*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
if __name__ == "__main__":
# pandas读入
data = pd.read_csv('Advertising.csv') # TV、Radio、Newspaper、Sales
x = data[['TV', 'Radio', 'Newspaper']]
# x = data[['TV', 'Radio']]
y = data['Sales']
print(x)
print(y)
# # 放在一起
plt.plot(data['TV'], y, 'ro', label='TV')
plt.plot(data['Radio'], y, 'g^', label='Radio')
plt.plot(data['Newspaper'], y, 'mv', label='Newspaer')
plt.legend(loc='lower right')
plt.grid()
plt.show()
# #
# # 分开绘制
# plt.figure(figsize=(9,12))
# plt.subplot(311)
# plt.plot(data['TV'], y, 'ro')
# plt.title('TV')
# plt.grid()
# plt.subplot(312)
# plt.plot(data['Radio'], y, 'g^')
# plt.title('Radio')
# plt.grid()
# plt.subplot(313)
# plt.plot(data['Newspaper'], y, 'b*')
# plt.title('Newspaper')
# plt.grid()
# plt.tight_layout()
# plt.show()
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
# print x_train, y_train
linreg = LinearRegression()
model = linreg.fit(x_train, y_train)
print (model)
print (linreg.coef_)
print (linreg.intercept_)
y_hat = linreg.predict(np.array(x_test))
mse = np.average((y_hat - np.array(y_test)) ** 2) # Mean Squared Error
rmse = np.sqrt(mse) # Root Mean Squared Error
print (mse, rmse)
t = np.arange(len(x_test))
plt.plot(t, y_test, 'r-', linewidth=2, label='Test')
plt.plot(t, y_hat, 'g-', linewidth=2, label='Predict')
plt.legend(loc='upper right')
plt.grid()
plt.show()
上面是基本的线性回归示例,下面是加上损失,也就是L1和L2正则的情况,相比较L2正则的结果更好,但是L1正则则可以得到稀疏的参数,能更利于后面的特征提取
#!/usr/bin/python
# -*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Lasso, Ridge
from sklearn.model_selection import GridSearchCV
if __name__ == "__main__":
# pandas读入
data = pd.read_csv('Advertising.csv') # TV、Radio、Newspaper、Sales
x = data[['TV', 'Radio', 'Newspaper']]
# x = data[['TV', 'Radio']]
y = data['Sales']
print(x)
print(y)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
# print x_train, y_train
model = Ridge()
#model = Lasso()
alpha_can = np.logspace(-3, 2, 10)
lasso_model = GridSearchCV(model, param_grid={'alpha': alpha_can}, cv=5)
lasso_model.fit(x, y)
print('验证参数:\n', lasso_model.best_params_)
y_hat = lasso_model.predict(np.array(x_test))
mse = np.average((y_hat - np.array(y_test)) ** 2) # Mean Squared Error
rmse = np.sqrt(mse) # Root Mean Squared Error
print (mse, rmse)
t = np.arange(len(x_test))
plt.plot(t, y_test, 'r-', linewidth=2, label='Test')
plt.plot(t, y_hat, 'g-', linewidth=2, label='Predict')
plt.legend(loc='upper right')
plt.grid()
plt.show()