0%

回归大家族

线性回归

公式: $\hat{y}=\theta_0+\theta_1x_1+\theta_2x_2+…+\theta_nx_n$

向量形式:$\hat{y}=h_\theta(\vec{x})=\vec{\theta_0^T}\cdot \vec{x}$

损失函数:$MSE(\vec{X},h_\theta)=\frac{1}{m}\sum_{i=1}^m(\vec{\theta_0^T}\cdot \vec{x^{(i)}}-y^{(i)})$

通过最小化MSE球的参数$\theta$,可得标准方程:$\hat{\theta}=(X^TX)^{(-1)}X^Ty$

1
2
3
4
%matplotlib inline
import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
1
2
X = 2 * np.random.rand(100,1)
y = 4 + 3 * X + np.random.randn(100,1)
1
2
lin_reg = LinearRegression()
lin_reg.fit(X, y)
LinearRegression()

sklearn中线性回归的重要属性和方法

  • intercept_表示偏置项
  • coef_表示权重
  • fit(X, y)表示拟合过程
  • predict(X, y)表示预测过程
  • score(X, y)对于线性回归表示相关系数
1
lin_reg.intercept_,lin_reg.coef_
(array([3.93410448]), array([[2.94751289]]))
1
2
3
4
plt.figure()
plt.scatter(X, y, c='b', s=2)
plt.plot(X, lin_reg.predict(X), color='red')
plt.text(1.6,4,'score:{:.2f}'.format(lin_reg.score(X,y)))
Text(1.6, 4, 'score:0.80')
png

梯度下降

中心思想:迭代的调整参数从而使损失函数最小化。

做法:通过测量参数向量$\theta$相关的误差函数和局部梯度,并沿着降低梯度的方向调整,直到梯度为0,到达最小值。

具体来说:首先使用一个随机的$\theta$值,然后逐步改进,每次踏出一步,每一步都尝试降低一点损失函数,直到算法收敛到一个最小值梯度下降中迭代的每一步的步长,叫做学习率,这是个超参数。

如果学习率过高,会导致算法发散,值越来越大;
如果学习率太低,算法需要经过大量迭代才能收敛,这将耗费很长时间。

梯度下降陷阱:在实际情况中,由于算法十分复杂,梯度有可能在未达到全局最小值时就不再下降,收敛到局部最小值在使用梯度下降时最好保证特征值的大小比例都差不多,对数据进行标准化或归一化后再进行训练。

批量梯度下降

要实现梯度下降,需要计算每个模型关于参数$\theta_j$的损失函数的梯度,在计算梯度下降的每一步时,都是基于完整的训练集X的,这就是为什么该算法叫批量梯度下降。但是面对非常庞大的数据集时,算法会变的极慢。但是比标准方程或是SVD快的多。

有了梯度向量,我们就得到了梯度下降的公式,其中$\eta$是学习率:

随机梯度下降

每一步在训练集中随机选择一个实例,并且仅基于该单个实例来计算梯度。

由于算法的随机性质,它比批量随机梯度下降要不规则的多,损失函数不再是缓缓降低直到最小值,而是不断上上下下,但总体来看还是缓慢下降直到收敛到最小值。当成本函数非常不规则时,随机梯度下降可以帮助算法跳出局部最小值。

随机性的好处是可以跳出局部最优,但缺点是永远定位不出最小值。要解决这个困难,一个好办法是逐步降低学习率,确定每个迭代学习率的函数叫做学习率调度。

注意:使用随机梯度下降时,训练实例必须独立且均匀分布,以确保平均而言将参数拉向全局最优,确保该点可以对实例进行随机混洗。

小批量梯度下降

在数据集中,随机取小型批量的实例集计算梯度。

多项式回归

对于非线性的数据我们仍可以用线性模型进行拟合,我们先将每个特征的幂次方添加为一个新特征,然后再训练线性模型。

当存在多个特征时,PolynomialFeatures可以将特征的所有组合添加到给定的多项式阶数,但要注意特征组合的数量爆炸。

1
from sklearn.preprocessing import PolynomialFeatures
1
2
X = 6*np.random.rand(100,1)-3
y = 0.5*X**2+X+2+np.random.randn(100,1)
1
2
3
poly = PolynomialFeatures(degree=2,include_bias=False)
X_poly = poly.fit_transform(X)
X_poly[0]
array([-2.82928969,  8.00488013])
1
2
3
poly_lin_reg = LinearRegression()
poly_lin_reg.fit(X_poly, y)
poly_lin_reg.intercept_,poly_lin_reg.coef_
(array([2.27141448]), array([[0.98932735, 0.41514151]]))
1
2
3
4
5
6
X_new = np.linspace(-3,3,100).reshape(-1,1)
y_new = poly_lin_reg.predict(poly.fit_transform(X_new))
plt.figure()
plt.scatter(X, y, c='b',s=2)
plt.plot(X_new,y_new,c='r')
plt.text(1.6,0,'score:{:.2f}'.format(poly_lin_reg.score(X_poly,y)))
Text(1.6, 0, 'score:0.84')
png

学习曲线

为了避免过拟合,有两种常用的方法:

  • 交叉验证:根据交叉验证的指标泛化较差而训练集上很好,说明过拟合;若两者的表现均不理想,则是欠拟合。
  • 学习曲线;绘制模型再训练集和验证集上关于训练集大小(或训练迭代)的性能函数。

欠拟合的学习曲线,训练误差和泛化误差都较高且最后都趋于平稳;过拟合时,泛化误差很高,而训练误差也会逐渐趋于平稳,其也较高。

1
2
3
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def my_plot(model,X,y):
X_train, X_val, y_train, y_val = train_test_split(X,y,test_size=0.2)
train_errors, val_errors = [],[]
for m in range(1,len(X_train)):
model.fit(X_train[:m], y_train[:m])
y_train_pred = model.predict(X_train[:m])
y_val_pred = model.predict(X_val)
train_errors.append(mean_squared_error(y_train[:m],y_train_pred))
val_errors.append(mean_squared_error(y_val,y_val_pred))
plt.plot(np.sqrt(train_errors),c='b',label='train')
plt.plot(np.sqrt(val_errors),c='r',label='validation')
plt.ylim(0,5)
plt.legend()
plt.grid(True)
1
2
3
4
5
lin = LinearRegression()
poly_lin = Pipeline([
('poly_feature',PolynomialFeatures(degree=100,include_bias=False)),
('linear',LinearRegression())
])
1
my_plot(lin,X,y)
png
1
my_plot(poly_lin,X,y)
png

正则化线性模型

减少过拟合的好方法是对模型进行正则化(约束模型):它拥有的自由度越少,过拟合数据的难度就越大。

岭回归

岭回归也称为Tikhonov正则化,是线性回归的正则化版本,将权重参数$\theta$的L2范数加入损失函数,迫使学习算法不仅拟合数据,还使模型权重尽可能的小。

注意,尽在训练期间将正则化参数添加到损失函数中,训练完成后要使用非正则化的性能度量来评估模型的性能。
在执行岭回归或者其他正则化模型之前,都要对数据特征进行缩放,因为其对数据缩放特征敏感。

岭回归的损失函数:

1
from sklearn.linear_model import Ridge
1
2
3
4
5
6
7
8
X_ = np.linspace(0,3,100).reshape(-1,1)
plt.figure()
for alpha in [0,10,100]:
ridge = Ridge(alpha=alpha)
ridge.fit(X,y)
plt.scatter(X,y,c='k',s=4)
plt.plot(X_,ridge.predict(X_),label='alpha={}'.format(alpha))
plt.legend()
png
1
2
3
4
5
6
7
8
9
10
11
12
X_ = np.linspace(0,3,100).reshape(-1,1)
plt.figure()
for alpha in [0,1e-5,1]:
pipe = Pipeline([
('0',PolynomialFeatures(degree=10,include_bias=False)),
('1',Ridge(alpha=alpha))
])
pipe.fit(X,y)
plt.scatter(X,y,c='k',s=4)
plt.plot(X_,pipe.predict(X_),label='alpha={}'.format(alpha))
plt.ylim(0,12)
plt.legend()
png
1
from sklearn.linear_model import SGDRegressor
1
2
3
4
5
6
7
8
plt.figure()
for alpha in [0,1e-5,1]:
sgd_reg = SGDRegressor(penalty='l2',alpha=alpha)
sgd_reg.fit(X,y.ravel())
plt.scatter(X,y,c='k',s=4)
plt.plot(X_,sgd_reg.predict(X_),label='alpha={}'.format(sgd_reg.alpha))
plt.ylim(0,12)
plt.legend()
png

Lasso回归

线性回归的另一种正则化叫做最小绝对收缩和选择算子回归,简称Lasso回归。他向随时函数添加权重向量的L1范数。

Lasso回归的一个重要特点是,他倾向于完全消除最不重要特征的权重,会自动执行特征选择并输出一个稀疏模型。

其损失函数如下:

为避免在最优解附近反弹,需要逐渐降低训练期间的学习率。

1
from sklearn.linear_model import Lasso
1
2
3
4
5
6
7
8
plt.figure()
for alpha in [0.5,1e-5,1]:
lasso_reg = Lasso(alpha=alpha)
lasso_reg.fit(X,y)
plt.scatter(X,y,c='k',s=4)
plt.plot(X_,lasso_reg.predict(X_),label='alpha={}'.format(lasso_reg.alpha))
plt.ylim(0,12)
plt.legend()
png

弹性网络

弹性网络是介于岭回归和Lasso回归的中间地带,正则项是权重系数的L1,L2范数的混合,用混合系数r控制。
大多数情况下,我们应避免使用纯线性回归,默认岭回归;担当实际用到的特征数很少时,应倾向于使用Lasso或弹性网络。
弹性网络的损失函数如下

1
from sklearn.linear_model import ElasticNet
1
2
3
4
5
6
7
8
plt.figure()
for alpha in [0.5,1e-5,1]:
elatic = ElasticNet(alpha=alpha,l1_ratio=0.5)
elatic.fit(X,y)
plt.scatter(X,y,c='k',s=4)
plt.plot(X_,elatic.predict(X_),label='alpha={},r={}'.format(elatic.alpha,elatic.l1_ratio))
plt.ylim(0,12)
plt.legend()
png

逻辑回归

逻辑回归被广泛用于估算一个实例属于某个特定类别的概率,若预估概率超过50%啧判定该例属于该类别,称为正例,记为1;反之则不属于该类别,称为反类,记为0。它的输出是结果的数理逻辑值。

逻辑回归模型的估计概率:

$\hat{p}=h_\theta(\vec{x})=\sigma(\vec{x^T}\vec{\theta})$

逻辑回归预测模型:

$\hat{y}=
\begin{cases}
0& \hat{p}<0.5\\
1& \hat{p}\ge0.5
\end{cases}$

单个训练实例的损失函数:

$c(\theta)=
\begin{cases}
-\log(\hat{p})& y=1\\
-\log(1-\hat{p})& y=0
\end{cases}$

逻辑回归损失函数:

$J(\theta)={1\over m} \sum_{i=1}^m[y^i\log(\hat{p}^i)+(1-y^i)\log(1-\hat{p}^i)]$

1
2
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
1
2
3
iris = load_iris()
X = iris['data'][:,3:]#取得第四个特征的每个值
y = (iris['target']==2).astype(np.int)
1
iris['feature_names']
['sepal length (cm)',
 'sepal width (cm)',
 'petal length (cm)',
 'petal width (cm)']
1
2
log_reg = LogisticRegression()
log_reg.fit(X,y)
LogisticRegression()
1
2
X_ = np.linspace(0,3,1000).reshape(-1,1)
y_ = log_reg.predict_proba(X_)#predict()返回的是概率最大的类别,predict_proba()返回每种类别的可能性
1
2
3
4
5
6
plt.figure(figsize=(10,5))
plt.plot(X_,y_[:,0],'g--',label='not virginica')
plt.plot(X_,y_[:,1],'b-',label='virginica')
plt.legend()
plt.plot(X[y==0], y[y==0], "gs")
plt.plot(X[y==1], y[y==1], "b^")
[<matplotlib.lines.Line2D at 0x1d311467520>]
png
1
log_reg.predict([[2.3],[1]])
array([1, 0])
1
log_reg.predict_proba([[2.3]])
array([[0.05889014, 0.94110986]])

Softmax回归

逻辑回归经过推广可以支持多个类别,称为softmax回归,或叫做多元逻辑回归。

给定一个实例x,Softmax回归模型首先计算出每个类k的分数,然后对这些分数应用softmax函数,估算出每个类的概率。

Softmax回归分类器一次只能预测一个类(多类一输出),因此他只能与互斥的类一同使用。

损失函数被称为交叉熵,用于衡量一组估算出的类的概率跟目标类的匹配程度。

Softmax函数:

$\hat{p}_k={{\exp(s_k(\vec{x}))} \over {\sum_{j=1}^K\exp(s_j(\vec{x}))}}$

回归分类预测:

$\hat{y}=argmax(\hat{p}_k)$

交叉熵损失函数:

$J(\theta)=-\frac{1}{m}\sum_{i=1}^m\sum_{k=1}^Ky_k^i\log(\hat{p}_k^i)$

1
2
X = iris['data'][:,(2,3)]
y = iris['target']
1
2
soft_reg = LogisticRegression(multi_class='multinomial',solver='lbfgs',C=10)
soft_reg.fit(X,y)
LogisticRegression(C=10, multi_class='multinomial')
1
soft_reg.predict([[5,2]])
array([2])
1
soft_reg.predict_proba([[5,2]])
array([[6.38014896e-07, 5.74929995e-02, 9.42506362e-01]])
1
2
x0,x1 = np.meshgrid(np.linspace(0,8,1000).reshape(-1,1),np.linspace(0,3.5,1000).reshape(-1,1))
X_ = np.c_[x0.ravel(),x1.ravel()]
1
2
y_prob = soft_reg.predict_proba(X_)
y_pred = soft_reg.predict(X_)
1
z=y_pred.reshape(x0.shape)
1
2
3
4
5
6
7
plt.figure(figsize=(10, 4))
plt.plot(X[y==2, 0], X[y==2, 1], "g^", label="Iris virginica")
plt.plot(X[y==1, 0], X[y==1, 1], "bs", label="Iris versicolor")
plt.plot(X[y==0, 0], X[y==0, 1], "yo", label="Iris setosa")
plt.contour(x0,x1,z)
plt.legend()
plt.axis([0,8,0,3.5])
(0.0, 8.0, 0.0, 3.5)
png

附录 参数列表

LinearRegression

参数 说明
normalize bool, default=False:如果为True,则在回归之前通过减去均值并除以l2-范数来对回归变量X进行归一化。
n_jobs int, default=None:设置用于计算的核心数。
属性 说明
coef_ 线性回归问题的估计系数。
intercept_ 线性模型中的截距项。

ElasticNet

参数 说明
alpha float, default=1.0:乘以惩罚项的常数。
l1_ratio float, default=0.5:弹性网络的混合系数。
max_iter int, default=1000:最大迭代次数。
tol float, default=1e-4:优化的容忍度。
warm_start bool, default=False:设置为True时,重用前面调用的解决方案来进行初始化,否则,只清除前面的解决方案。
normalize bool, default=False:如果为True,则在回归之前通过减去均值并除以l2-范数来对回归变量X进行归一化。
n_jobs int, default=None:设置用于计算的核心数。
属性 说明
coef_ 线性回归问题的估计系数。
intercept_ 线性模型中的截距项。

Lasso

参数 说明
normalize bool, default=False:如果为True,则在回归之前通过减去均值并除以l2-范数来对回归变量X进行归一化。
alpha float, default=1.0:乘以惩罚项的常数。
n_jobs int, default=None:设置用于计算的核心数。
max_iter int, default=1000:最大迭代次数。
tol float, default=1e-4:优化的容忍度。
warm_start bool, default=False:设置为True时,重用前面调用的解决方案来进行初始化,否则,只清除前面的解决方案。
属性 说明
coef_ 线性回归问题的估计系数。
intercept_ 线性模型中的截距项。

Ridge

参数 说明
normalize bool, default=False:如果为True,则在回归之前通过减去均值并除以l2-范数来对回归变量X进行归一化。
alpha float, default=1.0:乘以惩罚项的常数。
n_jobs int, default=None:设置用于计算的核心数。
max_iter int, default=1000:最大迭代次数。
tol float, default=1e-4:优化的容忍度。
warm_start bool, default=False:设置为True时,重用前面调用的解决方案来进行初始化,否则,只清除前面的解决方案。
属性 说明
coef_ 线性回归问题的估计系数。
intercept_ 线性模型中的截距项。

LogisticRegression

参数 说明
penalty {‘L1’, ‘L2’, ‘elasticnet’, ‘none’}, default=’L2’:用于指定处罚中使用的规范。
C float, default=1.0:正则强度的倒数;必须为正浮点数。
n_jobs int, default=None:设置用于计算的核心数。
max_iter int, default=1000:最大迭代次数。
tol float, default=1e-4:优化的容忍度。
warm_start bool, default=False:设置为True时,重用前面调用的解决方案来进行初始化,否则,只清除前面的解决方案。
class_weight dict or ‘balanced’, default=None:以{class_label: weight}的形式与类别关联的权重。如果没有给出,所有类别的权重都应该是1。
“balanced”模式使用y的值来自动调整为与输入数据中的类频率成反比的权重。
multi_class {‘auto’, ‘ovr’, ‘multinomial’}, default=’auto’:如果选择的选项是“ ovr”,则每个标签都看做二分类问题。对于“multinomial”,即使数据是二分类的,损失最小是多项式损失拟合整个概率分布。
属性 说明
coef_ 线性回归问题的估计系数。
intercept_ 线性模型中的截距项。
classes_ 分类器已知的类别标签列表。