Sklearn只是工具,底层的原理,数学公式的推导才是重中之重!!!
1. 普通最小二乘法
sklearn.linear_model.LinearRegression
1.1)参数说明
LinearRegression(fit_intercept=True,normalize=False,copy_X=True, n_jobs=1)
主要参数说明:
fit_intercept:是否有截据,如果没有则直线过原点。默认为True.
normalize:布尔型,默认为False,若fit_intercept参数设置False时,normalize参数无需设置;若normalize设置为True时,则输入的样本数据将(X-X均值)/||X||;若设置normalize=False时,在训练模型前, 可以使用sklearn.preprocessing.StandardScaler进行标准化处理。
n_jobs:默认值为1。计算时使用的核数。
属性:
coef_:回归系数(斜率) intercept_:截距项
主要方法:
①fit(X, y, sample_weight=None)
②predict(X) ③score(X, y, sample_weight=None)
1.2)代码示例
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split
# 加载数据
diabetes = datasets.load_diabetes()
X = diabetes.data[:,np.newaxis ,2] # 数据新增一维
y = diabetes.target
np.set_printoptions(precision=5)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
LR = LinearRegression(normalize=True) # 数据标准化
LR.fit(X_train, y_train) # 训练模型
print('intercept_:%.3f' % LR.intercept_) # 输出截距
print("coef: ", LR.coef_) # 输出斜率
# 均方误差
print('Mean squared error: %.3f' % mean_squared_error(y_test, LR.predict(X_test)))
print('Variance score: %.3f' % r2_score(y_test, LR.predict(X_test)))
# 1-((y_test - LR.predict(X_test)) ** 2).sum() / ((y_test - y_test.mean()) ** 2).sum()
print('score: %.3f' % LR.score(X_test, y_test))
# 绘图
plt.scatter(X_test, y_test, color='green')
plt.plot(X_test, LR.predict(X_test), color='red', linewidth=3)
plt.show()
'''
print(clf.get_params()) # 获取本次训练模型的参数值
print(clf.set_params(normalize=True)) # 修改模型的参数值
print(clf.get_params()) # 重新显示模型训练参数值
'''
1.3)方法局限
该方法依赖于模型各项的相互独立性。当各项是相关的,且设计矩阵 X 的各列近似线性相关(多重共线性),那么,设计矩阵会趋向于奇异矩阵,这种特性导致最小二乘估计对于随机误差非常敏感,可能产生很大的方差。
2.岭回归(基于L2)
sklearn.linear_model.Ridge,RidgeCV
2.1)参数说明
Ridge(alpha=1.0,fit_intercept=True, normalize=False,copy_X=True, max_iter=None, tol=0.001, solver=‘auto’, random_state=None)
主要参数说明(重复的不再赘述):
alpha:正则化系数。
max_iter:最大的迭代次数,int类型,默认为None
tol:精度,float类型,默认为0.001。就是解的精度。
random_state:sag的伪随机种子
solver:求解方法,str类型,默认为auto。可选参数为:auto、svd、cholesky、lsqr、sparse_cg、sag。
1)auto根据数据类型自动选择求解器。
2)svd使用X的奇异值分解来计算Ridge系数。对于奇异矩阵比cholesky更稳定。
3)cholesky使用标准的scipy.linalg.solve函数来获得闭合形式的解。
4)sag使用随机平均梯度下降。它也使用迭代过程,并且当n_samples和n_feature都很大时,通常比其他求解器更快。
2.2)代码示例
2.2.1)数据集来源
import numpy as np
import pandas as pd
from sklearn.datasets import fetch_california_housing as fch
# 加载数据集
house_value = fch()
x = house_value.data
y = house_value.target[:,np.newaxis] # 增加一个维度以便合并数据
data = np.hstack((x,y))
df = pd.DataFrame(data)
df.columns = ["住户收入中位数","房屋使用年代中位数","平均房间数目","平均卧室数目","街区人口",
"平均入住率","街区的纬度","街区的经度","y值"]
df.index.name="编号"
df.to_csv('../data/加利福尼亚房价.csv')
2.2.2)基于加利福尼亚房价数据进行训练
import numpy as np
import pandas as pd
from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split
# 加载数据集
df = pd.read_csv('../data/加利福尼亚房价.csv', index_col='编号')
X = df.iloc[:, 0:8]
y = df.iloc[:, 8]
np.set_printoptions(precision=5)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=420) # 划分数据集
# 采用岭回归训练模型 --- 定义正则项系数
reg = Ridge(alpha=1, normalize=True)
reg.fit(X_train, y_train)
print('intercept_:%.3f' % reg.intercept_) # 输出截距
print("coef: ", reg.coef_) # 输出斜率
print('r2_score: ', reg.score(X_test, y_test)) # R2指数
# reg.set_params(alpha=0.6)#重新设置参数alpha=0.6
2.2.3)设置正则化参数:广义交叉验证(RidgeCV)
from sklearn.linear_model import RidgeCV
from sklearn.model_selection import train_test_split
# 加载数据集
df = pd.read_csv('../data/加利福尼亚房价.csv', index_col='编号')
X = df.iloc[:, 0:8] # 提取数据集
y = df.iloc[:, 8] # 提取标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=40)
# 有待验证,因为结果总是设置的最小的alpha值,可能是参数设置问题
# 通过RidgeCV可以设置多个参数值,算法使用交叉验证获取最佳参数值
reg = RidgeCV(alphas=np.arange(1,1000,200), normalize=True,fit_intercept=True,cv=5)
reg.fit(X_train, y_train)
print(reg.alpha_) # 最优的惩罚项,用此值再进行训练
2.2.4)探索交叉验证下,岭回归与线性回归的结果变化(推荐)
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.linear_model import Ridge, LinearRegression
from sklearn.model_selection import cross_val_score
# 加载数据集
df = pd.read_csv('../data/加利福尼亚房价.csv', index_col='编号')
X = df.iloc[:, 0:8] # 提取数据集
y = df.iloc[:, 8] # 提取标签
# 交叉验证下,岭回归与线性回归的结果变化
alpha_range = np.arange(1,1000,100)
ridge,lr = [],[]
for alpha in alpha_range:
reg = Ridge(alpha=alpha)
linear = LinearRegression()
# .mean()换成 .var()即可求得方差曲线
regs = cross_val_score(reg,X,y,cv=5,scoring='r2').mean()
linears = cross_val_score(linear,X,y,cv=5,scoring="r2").mean()
ridge.append(regs)
lr.append(linears)
plt.plot(alpha_range,ridge,c='red',label='Ridge')
plt.plot(alpha_range,lr,c='orange',label='LR')
plt.title('Mean')
plt.legend()
plt.show()
结论:通过图形可以看出,线性回归处理的结果始终不变,但是岭回归处理的结果在alpha处于0-100时,有略微提升(不到0.001),但是随着alpha的进一步增大,R2指数大幅下降,但是总体下降也保持在0.006左右。所以,整体来看,加利佛尼亚房屋价值数据集存在轻微的多重共线性。
技巧:
① R2指数 ---- mean():可以先设定alpha范围进行搜索,观察图形后再细化搜索最优的alpha(最大值)。
② R2指数 ---- var() :若图像随着alpha的逐渐变大,方差是急剧减小的,则模型逐渐趋于稳定。
2.3)方法优点
Ridge 回归用于解决两类问题:一是样本少于变量个数,二是变量间存在共线性
alpha 是控制系数收缩量的复杂性参数: alpha 的值越大,收缩量越大,模型对共线性的鲁棒性也更强。能够处理多重共线性问题。
3.Lasso回归(基于L1)
sklearn.linear_model.Lasso,LassoCV,LassoLarsCV(推荐)
3.1)参数说明
Lasso主要参数说明(重复的不再赘述):
tol:一个浮点数,指定判断迭代收敛与否的一个阈值。
warm_start:一个布尔值。如果为True,那么使用前一次训练结果继续训练,否则从头开始训练。
positive:一个布尔值。如果为True,那么强制要求权重向量的分量都为整数。
selection:一个字符串,可以选择‘cyclic’或者‘random’。
LassoCV(eps=0.001, n_alphas=100, alphas=None, fit_intercept=True, normalize=False, precompute=‘auto’, max_iter=1000, tol=0.0001, copy_X=True, cv=None, verbose=False, n_jobs=None, positive=False, random_state=None, selection=‘cyclic’)
LassoCV主要参数说明(重复的不再赘述):
eps:路径长度。eps=1e-3即alpha_min / alpha_max = 1e-3。
n_alphas:正则化路径中alpha的个数。
alphas:alpha组成的list。如果为None,自动选择alpha。
precompute:对于稀疏数据,通常令precompute=True,保留稀疏性。
cv: 确定交叉验证划分策略。
属性:
alpha_:交叉验证选择的惩罚项。 alphas_: alpha网格。
mse_path_: 每一个alpha、每一折交叉验证的测试集均方误差。
dual_gap_: 最佳alpha(alpha_)优化结束时的dual gap。
LassoLarsCV(fit_intercept=True, verbose=False, max_iter=500, normalize=True, precompute=‘auto’, cv=None, max_n_alphas=1000, n_jobs=None, eps=2.2e-16, copy_X=True, positive=False)
LassoLarsCV主要参数说明(重复的不再赘述):
verbose: bool or int, default=False 设置详细程度。
max_n_alphas:int,default=1000 交叉验证中用于计算残差的路径上的最大点数
3.2)代码示例
3.2.1) LassoCV和LassoLarsCV比较后者更优
LassoLarsCV 在寻找 alpha参数值上更具有优势
from sklearn.linear_model import LassoCV,LassoLarsCV
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=40) # 划分数据集
reg = LassoCV(alphas=np.arange(1,1000,100),cv=10)
reg.fit(X_train,y_train)
print('r2_score: ', reg.score(X_test, y_test)) # R2指数
plt.plot(np.arange(1,1000,100),reg.mse_path_,color='red')
plt.show()
reg = LassoLarsCV(cv=10)
reg.fit(X_train,y_train)
print('r2_score: ', reg.score(X_test, y_test))
3.3)方法优点
Lasso回归和岭回归的区别在于它的惩罚项是基于L1的范数,因此,它可以将系数控制收缩到0,从而达到变量选择的效果。能够处理多重共线性问题。
4.贝叶斯岭回归(推荐)
from sklearn.linear_model import BayesianRidge
4.1)参数说明
BayesianRidge(n_iter=300, tol=0.001, alpha_1=1e-06, alpha_2=1e-06, lambda_1=1e-06, lambda_2=1e-06, alpha_init=None, lambda_init=None, compute_score=False, fit_intercept=True, normalize=False, copy_X=True, verbose=False)
BayesianRidge主要参数说明:
alpha_1 : 超参数:伽马分布的形状参数优先于alpha参数。
alpha_2 : 超参数:伽马分布的反比例参数(速率参数)优先于阿尔法参数。
lambda_1 : 超参数:Gamma分布的形状参数优先于lambda参数。
lambda_2 : 超参数:伽马分布在lambda参数之前的逆比例参数(速率参数)。
alpha_init : alpha(噪声精度)的初始值。若未设置,alpha_init为1/Var(y)。
lambda_init : lambda(权重精度)的初始值。若未设置,lambda_init为1。
compute_score : 如果为真,则在每次优化迭代时计算对数边际似然。
verbose : 拟合模型时的详细模式。
属性 :
coef_ : 回归模型的系数(分布平均值) lambda_ : 权重的估计精度。
alpha_ : 噪声的估计精度。 sigma_ : 权重的估计方差协方差矩阵
X_offset_ : 如果normalize=True,则将居中数据的偏移量减去零平均值。
ARDRegression参数在BayesianRidge基础上加个threshold_lambda
threshold_lambda : 从计算中高精度删除(修剪)权重的阈值。
4.2)代码示例
from sklearn.linear_model import BayesianRidge, ARDRegression
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2, random_state=40) # 划分数据集
reg = BayesianRidge() # reg = ARDRegression()
reg.fit(X_train, y_train)
print('r2_score: ', reg.score(X_test, y_test)) # R2指数
4.3)方法优缺
贝叶斯回归有如下几个优点:
- 它能根据已有的数据进行改变。
- 它能在估计过程中引入正则项。
贝叶斯回归有如下缺点:
- 它的推断过程是非常耗时的。
5.随机梯度下降
from sklearn.linear_model import SGDRegressor
5.1)参数说明
SGDRegressor(loss=‘squared_loss’,penalty=‘l2’,alpha=0.0001, l1_ratio=0.15, fit_intercept=True, max_iter=1000, tol=0.001, shuffle=True, verbose=0, epsilon=0.1, random_state=None, learning_rate=‘invscaling’, eta0=0.01, power_t=0.25, early_stopping=False, validation_fraction=0.1, n_iter_no_change=5, warm_start=False, average=False)
SGDRegressor主要参数说明:
loss : 要使用的损失函数: ‘squared_loss’(普通最小二乘法), ‘huber’(huber回归), ‘epsilon_insensitive’(线性支持向量), or ‘squared_epsilon_insensitive’
penalty : {‘l2’, ‘l1’, ‘elasticnet’}, default=’l2’
alpha : 乘以正则化项的常数。值越高,正则化越强。
当设置为learning_rate为“optimal”时,也用于计算学习率。
l1_ratio : float, default=0.15 (仅当惩罚为“弹性网”时使用)
early_stopping :
验证分数未提高时,是否使用提前停止终止培训。
如果设置为True,它将自动留出一小部分训练数据作为验证,并在分数方法
返回的验证分数在n_iter_no_change连续历次中没有至少提高tol时终止训练.
5.2)代码示例
from sklearn.linear_model import SGDRegressor
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
from sklearn.model_selection import train_test_split
# 加载数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=33) # 划分数据集
sgd = SGDRegressor()
sgd.fit(X_train, y_train)
y_pred = sgd.predict(X_test)
# 性能评估
print(sgd.score(X_test, y_test))
print(r2_score(y_test, y_pred))
print(mean_squared_error(y_test, y_pred))
print(mean_absolute_error(y_test,y_pred))
5.3)方法优点
它支持用不同的损失函数和惩罚来拟合线性回归模型。 SGDRegressor 非常适用于有大量训练样本(>10000)的回归问题。
6.多项式回归
一般的回归可以处理多个自变量但它依旧是条直线不符合实际情况,故而可采用多项式进行拟合。PolynomialFeatures可以适用于单变量或多变量多项式拟合,可以找到最优的曲线。
from sklearn.preprocessing import PolynomialFeatures
6.1)参数说明
sklearn.preprocessing.PolynomialFeatures(degree=2, interaction_only=False, include_bias=True, order=‘C’)
主要参数说明 :
★ degree : 多项式特征的次数.
interaction_only : 默认为 False,如果为 True 则产生相互影响的特征集。
include_bias : 如果为真(默认),则包括一个偏差列,其中所有多项式幂均为零的特征(即1列-在线性模型中充当截距项)
order : {‘C’, ‘F’}, default=’C’
属性 :
powers_ : 幂[i,j]是第i个输出中第j个输入的指数.
n_input_features_ : 输入要素的总数.
n_output_features_ : 多项式输出特征的总数。输出特征的数量是通过迭代所有大小合适的输入特征组合来计算的。
方法 :
★fit(X, y=None) : 计算输出特征的数量
★transform(X) : 将数据转换为多项式特征
★fit_transform(X, y=None, fit_params) : 适应数据,然后对其进行转换.
★get_feature_names(input_features=None) : 返回输出要素的要素名称
★get_params : 获取此估计器的参数.
6.2)代码示例(均为单变量拟合)
6.2.1)PolynomialFeatures + LinearRegression
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
# 加载数据集
df = pd.read_csv('../data/加利福尼亚房价.csv', index_col='编号')
x = df.iloc[:, 0]
y = df.iloc[:, 8]
x = np.array(x).reshape(len(x), 1) # 转换为列向量
y = np.array(y).reshape(len(y), 1)
# 特征矩阵模型构建用来多项式的特征矩阵
poly_features = PolynomialFeatures(degree=2, include_bias=False)
poly_x = poly_features.fit_transform(x) # 通过模型转换x数据
model = LinearRegression()
model.fit(poly_x,y) # 这里使用转换后的特征矩阵相当于将一元2次转换为二元一次
plt.scatter(x,y,color='red',label='test data')
plt.plot(x,model.predict(poly_x),color='green',label='pred data')
plt.legend()
plt.show()
6.2.2) 通过 make_pipeline 封装起来使用
"""
更高次多项式回归预测
"""
from sklearn.pipeline import make_pipeline
X_train = X_train.reshape(len(X_train),1)
X_test = X_test.reshape(len(X_test),1)
y_train = y_train.reshape(len(y_train),1)
for m in [3, 4, 5]:
model = make_pipeline(PolynomialFeatures(m, include_bias=False), LinearRegression())
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print("{} 次多项式回归平均绝对误差: ".format(m), mean_absolute_error(y_test, y_pred.flatten()))
print("{} 次多项式均方根误差: ".format(m), mean_squared_error(y_test, y_pred.flatten()))
print("---")
6.2.3)几次项才是最佳的选择
"""
计算 m 次多项式回归预测结果的 MSE 评价指标并绘图
"""
m = 1 # 初始 m 值
mse = [] # 用于存储各最高次多项式 MSE 值
m_max = 10 # 设定最高次数
while m <= m_max:
model = make_pipeline(PolynomialFeatures(m, include_bias=False), LinearRegression())
model.fit(X_train, y_train) # 训练模型
y_pred = model.predict(X_test) # 测试模型
mse.append(mean_squared_error(y_test, y_pred.flatten())) # 计算 MSE
m = m + 1
# 绘图
plt.plot([i for i in range(1, m_max + 1)], mse, 'b')
plt.scatter([i for i in range(1, m_max + 1)], mse)
plt.title("MSE of m degree of polynomial regression")
plt.xlabel("m")
plt.ylabel("MSE")
plt.show()
6.3)方法优点
PolynomialFeatures方法只是将多项式中高次的项通过换元转换成多元一次的,即生成对应次项的特征矩阵,随后即可采用上述的回归方法进行训练,其评价指标也基本不变。
7. Pipeline 机制
from sklearn.pipeline import Pipeline
7.1)参数说明
sklern.pipeline.Pipeline(steps, memory=None, verbose=False)
主要参数说明:
★★ steps : 设定流水线上的一道道工序,并给这一道道工序起一个名字。
首先sklearn规定它是一个[( ),( )]类型,列表里面是一个个元组,分别为名字和工序,从左到右是流水线上的先后顺序。前面n-1道手续必须要拥有fit和transform两个函数,最后一个工序,虽然他就是个estimator,只需要fit就行.
verbose : default=False,用来显示每个流水线所消耗的时间,默认为False,即不显示。
方法:
1.同样是几个类似的函数。fit, fit_transform, get_params, predict, 这几个函数和前面的用法是一样的。
2.其他方法也基本一致。
7.2)代码示例
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
# 加载数据集
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/'
'breast-cancer-wisconsin/wdbc.data', header=None)
# y为字符型标签
# 使用LabelEncoder类将其转换为0开始的数值型
X, y = df.values[:, 2:], df.values[:, 1]
encoder = LabelEncoder()
y = encoder.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=0)
pipe_lr = Pipeline([('sc', StandardScaler()),
('pca', PCA(n_components=2)),
('clf', LogisticRegression(random_state=1))
],verbose=True)
pipe_lr.fit(X_train, y_train)
print('Test accuracy: %.3f' % pipe_lr.score(X_test, y_test))
7.3)方法优点
采用流水线的方式提高的码代码的效率。
补充
学习的目的是学到隐含在数据背后的规律,对具有同一规律的学习集以外的数据,经过训练的网络也能给出合适的输出,该能力称为泛化能力。
泛化误差反映了学习方法的泛化能力,如果一种方法学习的模型比另一种方法学习的模型具有更小的泛化误差,那么这种方法就是有效。事实上,泛化误差就是所学习到的模型的期望风险。
泛化误差 = 偏差 + 方差 + 噪声
学习算法的预测误差, 或者说泛化误差(generalization error)可以分解为三个部分: 偏差(bias), 方差(variance) 和噪声(noise). 在估计学习算法性能的过程中, 我们主要关注偏差与方差. 因为噪声属于不可约减的误差 (irreducible error).
1、偏差表示学习算法的期望预测与测试集标签的偏离程度,即刻画了学习算法本身的拟合能力。训练模型越复杂,则偏差越小,如线性回归可以通过增加参数个数来提高模型的复杂度,神经网络可以通过增加隐单元个数来提高模型的复杂度。
2、方差表示同样大小的训练数据集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响。若模型处于过拟合状态,不同训练数据集产生的学习模型相差较大。
3、噪声表示任何学习模型所能达到期望泛化误差的下界,即刻画了学习问题本身的难度。若噪声比较大,即使是最优模型,泛化误差也比较大。