import sklearn import preprocessing
,该模块专门用于数据的预处理,主要有均值移除(标准化),范围缩放,归一化,二值化,独热编码,标签编码由于每个样本的不同特征差异较大,不利于使用现有机器学习算法进行样本处理,均值移除可以让样本矩阵中的每一列平均值为0,标准差为1(mean=0,std=1)
如何做?
1.先求出一列特征的均值
2.再用每个特征值 - 均值
一列特征 17,20,23
mean=(17+20+23)/3=20
特征变成:-3,0,3
3.求出被均值后的标准差
4.用(-3,0,3)每个数除以标准差,将标准差变为1
s=std(-3,0,3)
[-3/s,0/s,3/s]
coding实现
import sklearn import preprocessing
A=preprocessing.scale(array) # A是均值移除后的结果,array是输入数组
将样本矩阵中的每列最小值和最大值设定为相同的区间,同一各列特征值的范围,一般情况下会把特征值缩放到[0,1]区间
如何做?
1.每个元素减去特征值数组中的最小元素
2.第一步得到的结果中每个元素除以最大值
例如有一列特征值表示年龄: [17, 20, 23]
每个元素减去特征值数组所有元素的最小值即可:[0, 3, 6]
[0, 3, 6]
把特征值数组的每个元素除以最大值即可:[0, 1/2, 1]
coding 实现
# 创建MinMaxScaler对象,其中feature_range()是缩放范围
mms=preprocessing.MinMaxScaler(feature_range(0,1))
# result是缩放后的结果
result=mms.fit_transform(array)
有些情况下,每个样本的特征值的具体数值不重要,但是每个样本特征值占比很重要,这时需要用到归一化处理
如何做?
1.用每个样本的每个特征值除以该样本各个特征值绝对值的总和
2.变换后的样本矩阵,每个样本的特征绝对值之和为1(其实就是总面积为1,把它分块了)
coding实现
# array->原始矩阵
# norm->范数
# l1 - l1范数,向量中个元素绝对值之和
# l2 - l2范数,向量中个元素平方之和
# result 返回归一化处理后的矩阵
result=preprocessing.normalize(array,norm='l1')
# 创建一个二值化对象,给出阈值
bin=preprocessing.Binarizer(threshold=阈值)
# 输入元素数据array,返回result
result=bin.transform(array)
为样本特征的每个值建立一个由1和若干个0组成的序列,用该序列对所有特征值进行编码
如何做?
两个数 三个数 四个数
1 3 2
7 5 4
1 8 6
7 3 9
为每一个数字进行独热编码:
1-10 3-100 2-1000
7-01 5-010 4-0100
8-001 6-0010
9-0001
编码完毕后得到最终经过独热编码后的样本矩阵:
101001000
010100100
100010010
011000001
coding实现
# 创建一个独热编码器
# sparse:是否使用缩紧格式(稀疏矩阵)
ohe=preprocessing.OneHotEncoder(sparse=是否采用缩紧格式,dtype=数据类型)
# 对原始样本array进行处理,返回结果
result=ohe.fit_transform(array)
------------------------------------------------------------------
ohe = sp.OneHotEncoder(sparse=是否采用紧缩格式, dtype=数据类型)
# 对原始样本矩阵进行训练,得到编码字典
encode_dict = ohe.fit(array)
# 调用encode_dict字典的transform方法 对数据样本矩阵进行独热编码
result = encode_dict.transform(array)
根据字符串形式的特征值在特征序列中的位置,为其制定一个数字标签,用于提供给基于数值算法的学习模型
coding实现
# 获取标签编码器
lbe = sp.LabelEncoder()
# 调用标签编码器的fit_transform方法训练并且为原始样本矩阵进行标签编码
result = lbe.fit_transform(array)
# 根据标签编码的结果矩阵反查字典 得到原始数据矩阵
samples = lbe.inverse_transform(result)
预测函数 y = w 0 + w 1 x y=w_0+w_1x y=w0+w1x
x:输入
y:输出
w 0 , w 1 w_0,w_1 w0,w1:模型参数
所谓训练模型,就是根据已知的x和y,找到最佳的模型参数 w 0 , w 1 w_0,w_1 w0,w1,尽可能的精确描述输入和输出的关系
**单样本误差:**根据预测函数求出输入为x时的预测值: y i ′ = w 0 + w 1 x y_i'=w_0+w_1x yi′=w0+w1x,单样本误差为 1 2 ( y i ′ − y ) 2 \frac{1}{2}(y_i'-y)^2 21(yi′−y)2,
**总样本误差:**把所有单样本误差相加即时总样本误差: 1 2 ∑ i = 1 n ( y i ′ − y ) 2 \frac{1}{2}\sum_{i=1}^n(y_i'-y)^2 21∑i=1n(yi′−y)2
损失函数: l o s s = 1 2 ∑ i = 1 n ( w 0 + w 1 x i − y ) 2 loss=\frac{1}{2}\sum_{i=1}^n(w_0+w_1x_i-y)^2 loss=21∑i=1n(w0+w1xi−y)2
所以损失函数就是总样本误差关于模型参数的函数,该函数属于三维数学模型,即需要找到一组 w 0 , w 1 w_0,w_1 w0,w1使得loss取得最小值
coding实现
from sklearn.linear_model import LinearRegression
# 创建一个线性回归模型
model=LinearRegression()
# 训练模型,使用训练数据集
model.fit(x_train,y_train)
# 预测模型,得到预测结果
result=model.predict(x_test)
# 评估模型,得到分数
model.score(x_test,y_test)
评估训练结果误差(metrics)
线性回归模型训练完毕后,可以利用测试集评估训练误差,sklearn.metrics
提供了相应的常用方法
from sklearn import metrics
# 平均绝对值误差
metrics.mean_absolute_error(y,pred_y)
# 平均均方误差,在平均绝对值误差的基础上**2
metrics.mean_squared_error(y,pred_y)
# 中位绝对值误差
metrics.median_absolut_error(y,pred_y)
# r2得分(0,1]区间的分值,分数越高,误差越小
metrics.r2_score(y,pred_y)
模型的保存和加载
模型训练是个耗时的过程,可以将训练的模型保存到磁盘中,也可在需要的时候从磁盘加载,不需要重新训练
coding实现:
import pickle
pickle.dump(内存对象,磁盘文件)
model=pickle.load(磁盘文件)
--------------------------------------------------
with open(path,'rb') as f:
model=pickle.load(f)
一元多项式回归: y = w 0 + w 1 x + w 2 x 2 + w 3 x 3 + . . . + w d x d y=w_0+w_1x+w_2x^2+w_3x^3+...+w_dx^d y=w0+w1x+w2x2+w3x3+...+wdxd
将高次项看做对一次项特征的扩展得到: y = w 0 + w 1 x 1 + w 2 x 2 + w 3 x 3 + . . . + w d x d y=w_0+w_1x_1+w_2x_2+w_3x_3+...+w_dx_d y=w0+w1x1+w2x2+w3x3+...+wdxd,那么一元多项式回归即可看做为多元线性回归,可以使用LinearRegression
模型对样本数据进行模拟训练,所以一元多项式回归的实现需要两个步骤:
1.将一元多项式回归问题转换为多元线性回归问题(只需给出多项式最高次数即可)
2.将1步骤的到多项式的结果中 w 1 , w 2 . . . w_1,w_2... w1,w2...,当做样本特征,交给线性回归器训练多元线性模型
使用sklearn提供的数据管线实现
coding实现:
from sklearn import pipeline
from sklearn import preprocessing
from sklearn.linear_model import LinearRegression
# PolynomialFeature->多项式特征扩展器,里面填扩展的最高次数
model=pipeline.make_pipeline(preprocessing.PolynomialFeature(10),
LinearRegression())
model.fit(x_train,y_train)
result=model.predict(x_test)
损失函数计算的是一个样本上的误差
代价函数计算的是整个数据集上的误差,可以理解为多个损失函数之和
使用多项式回归,如果多项式最高次项比较大,模型就容易出现过拟合,正则化是一种常见的防止过拟合的方法,一般原理是在损失函数后面加上一个对参数的约束项,这个约束项叫做正则化项(regularizer),在线性模型回归中,通常有两种不同的正则化项:
1.**L1正则化:**加上所有参数(不包括0次项)的绝对值之和,即L1正则化,此时叫做Lasso回归
2.**L2正则化:**加上所有参数(不包括0次项)的平方和,即L2正则化,此时叫做岭回归
损失函数图像(选择直线方程进行优化)
假设直线方程: h ^ θ = θ 0 + θ 1 x \hat{h}_{\theta} = \theta_0 + \theta_1 x h^θ=θ0+θ1x,该方程只有一个特征x,两个参数 θ 0 , θ 1 \theta_0,\theta_1 θ0,θ1
对应的损失函数 J ( θ ) = 1 m ∑ i = 1 m ( θ 0 + θ 1 x ( i ) − y ( i ) ) 2 J(\theta) = \frac{1}{m} \sum_{i=1}^{m}{(\theta_0 + \theta_1 x^{(i)} - y^{(i)})^2} J(θ)=m1∑i=1m(θ0+θ1x(i)−y(i))2,该代价函数为均方误差(MSE),其中m是样本量,去一个样本点(1,1)带入上述损失函数,可得 J ( θ ) = ( θ 0 + θ 1 − 1 ) 2 J(\theta)=(\theta_0+\theta_1-1)^2 J(θ)=(θ0+θ1−1)2,该式是一个一元二次方程,可以画出其三维空间图(由于多个样本点的损失函数式所有样本点损失函数之和,且不同样本点只是相当于改变了损失函数中两个变量的参数,因此多样本的损失函数MSE图像只会在下图发生缩放和平移,不会发生过大的形变)
使用 J J J轴表示蓝色轴线,上方为正向
θ 1 \theta_1 θ1表示红色轴线,左边为正向
使用 θ 0 \theta_0 θ0表示绿色轴线,指向屏幕外的方向为正向.
正则化的图像(以L1正则化为例)
J ( θ ) = 1 m ∑ i = 1 m ( θ 0 + θ 1 x ( i ) − y ( i ) ) 2 + λ ∣ ∣ θ 1 ∣ ∣ 1 J(\theta) = \frac{1}{m} \sum_{i=1}^{m}{(\theta_0 + \theta_1 x^{(i)} - y^{(i)})^2} + \lambda ||\theta_1||_1 J(θ)=m1∑i=1m(θ0+θ1x(i)−y(i))2+λ∣∣θ1∣∣1, λ \lambda λ,是正则化项的参数,此处取1(为了方便),由于正则化项不包含截距项(0次项),此时的L1正则化相当于参数 θ 1 \theta_1 θ1的绝对值,其图像如下:
将两张图片重合,可得到下图:
两个方程相加后,即 J ( θ ) = ( θ 0 + θ 1 − 1 ) 2 + ∣ θ 1 ∣ J(\theta)=(\theta_0+\theta_1-1)^2+|\theta_1| J(θ)=(θ0+θ1−1)2+∣θ1∣,可得到一下图像:
公式 J ( θ ) = ( θ 0 + θ 1 − 1 ) 2 + λ ∣ θ 1 ∣ J(\theta)=(\theta_0+\theta_1-1)^2+\lambda|\theta_1| J(θ)=(θ0+θ1−1)2+λ∣θ1∣,在第一项的值非常小,但第二项额值非常大的区域,这些值会受到正则化的巨大影响,从而使这些区域的值与正则化项近似,例如,原来的损失函数 θ 0 = − θ 1 \theta_0=-\theta_1 θ0=−θ1, J J J,轴方向上的值始终为0,但是假如正则化项 J = ∣ θ 1 ∣ J=|\theta_1| J=∣θ1∣后,该直线原来上为0的点都变成了 θ 1 \theta_1 θ1的绝对值,这就像和加权平均一样,哪一项的权重越大,对最终结果产生的影响也越大
想象一种极端情况:在参数的整个定义域中,第二项的取值都远远大于第一项,那么最终的损失函数几乎由第二项决定,也就是整个代价函数的图像会非常类似于 J = ∣ θ 1 ∣ J=|\theta_1| J=∣θ1∣,而不是原来的MSE损失函数,这就相当于在 λ \lambda λ取值过大的情况,最终的全局最优解都将会是坐标的原点
岭回归与多项式回归的不同在于代价函数上的差别,岭回归的代价函数如下:
J ( θ ) = 1 2 m ∑ i = 1 m ( y ( i ) − ( w x ( i ) + b ) ) 2 + λ 2 ∣ ∣ w ∣ ∣ 2 2 = 1 2 M S E ( θ ) + λ 2 ∑ i = 1 n θ i 2 ⋯ ( 1 − 2 ) J(\theta) = \frac{1}{2m} \sum_{i=1}^{m}{(y^{(i)} - (w x^{(i)} + b))^2} + \frac{\lambda}{2} ||w||_2^2 = \frac{1}{2}MSE(\theta) + \frac{\lambda}{2} \sum_{i = 1}^{n}{\theta_i^2} \ \quad \cdots \ (1 - 2) J(θ)=2m1∑i=1m(y(i)−(wx(i)+b))2+2λ∣∣w∣∣22=21MSE(θ)+2λ∑i=1nθi2 ⋯ (1−2)
其中w是长度为n的向量,不包括截距项的系数 θ 0 \theta_0 θ0; θ \theta θ是长度为n+1的向量,包括截距项的系数 θ 0 \theta_0 θ0,m为样本数,n为特征数
可以看到岭回归的正则项是L2正则
核心思想:相似的输入必定会产生相似的输出
从训练样本中选择第一个特征进行子表划分,使每个子表中该特征的值全部相同,然后再在每个子表中选择下一个特征,按照同样的规则继续划分更小的子表,不断重复直到所有的特征全部使用完为止,此时便得到叶级子表,其中所有样本的特征值全部相同,对于待测样本,根据其每一个特征的值,选择对应的子表,逐一匹配,直到找到与之完全匹配的叶级子表,用该子表中样本的输出,通过平均(回归)或者投票(分类)为待测样本提供输出
随着子表的划分,信息熵(信息的混乱程度)越来越小,信息越来越纯,数据越来越有序
coding实现
import sklearn.tree as st
# 创建决策树回归模型,max_depth表示数的最大深度
model=st.DecisionTreeRegressor(max_depth=4)
model.fit(x_train,y_train)
result=predict(x_test)
首先为样本矩阵中的样本随机分配初始权重,由此构建一颗带有权重的决策树,在由该决策树提供预测输出时,通过加权平均或者加权投票的方式产生预测值,将训练样本带入模型,预测其输出,对那些预测值与实际值不同的样本,提高其权重,由此形成第二棵决策树,重复以上过程,构建出不同权重的若干棵决策树
coding实现
import sklearn.tree as st
import sklearn.ensemble as se
# 创建决策树模型
model=st.DecisionTreeRegressor(max_depth=4)
# 自适应增强决策树回归模型 n_estimator:构建XXX棵不同权重的决策树,训练模型
model=se.AdaBoostRegressor(model,n_estimators=400,random_state=7)
model.fit(x_train,y_train)
result=model.predict(x_test)
作为决策树模型训练过程的副产品,根据每个特征划分子表前后的信息熵减少量就标志了该特征的重要程度,此纪委该特征重要性指标,训练得到的模型对象提供了feature_importance_
来存储每个特征的重要性
model.fit(x_train,y_train)
feature_importance=model.feature_importance_
在自助聚合的基础上,每次构建决策树模型时,不仅随机选择部分样本,而且还随机选择部分特征,这样的集合算法,不仅规避了强势样本对预测结果的影响,而且也削弱了强势特征的影响,提高模型的泛化能力
coding实现
import sklearn.ensemble as se
# 构建随机森林模型,max_depth:决策树最大深度
# n_estimators:构建的决策树数量
# min_sample_split:子表中最小样本数,若小于这个数字,则不再向下拆分
model=se.RandomForestRegressor(max_depth=10,n_estimators=1000,
min_samples_split=2)
通过输入的样本数据,基于多元线性回归模型求出线性预测方程:
y = w 0 + w 1 x + w 2 x y=w_0+w_1x+w_2x y=w0+w1x+w2x
但是,通过线性回归方程返回的是连续值,不可以直接用于业务模型,所以需要一种方式将连续的预测值变成离散值(只有两个类别,通常是1,0)
逻辑函数(sigmoid): y = 1 1 + e − x y=\frac{1}{1+e^{-x}} y=1+e−x1,(一个十分经典的激活函数 activation function),该逻辑函数,当x>0时,y>0.5;当x<0时,y<0.5,可以实现将连续的输入值转化为(0,1)区间上的值,选择概率大的类别作为分类预测结果,是线性函数非线性化的一种方式
coding实现:
import sklearn.linear_model import LogisticRegression
# 构建逻辑回归器
# solver:逻辑函数中指数的函数关系(liblinear为线性函数关系)
# C:正则强度,C越大,拟合效果越小,范性越好
model=LogisticRegression(solver='liblinear',C=正则强度)
model.fit(x_train,y_train)
result=model.predict(x_test)
朴素贝叶斯分类是一种依据概率理论实现的分类方式
贝叶斯定理(公式): P ( A ∣ B ) = P ( B ∣ A ) P ( A ) P ( B ) P(A|B)=P(B|A)P(A)P(B) P(A∣B)=P(B∣A)P(A)P(B)
P ( A , B ) = P ( A ) P ( B ∣ A ) = P ( B ) P ( A ∣ B ) P(A,B)=P(A)P(B|A)=P(B)P(A|B) P(A,B)=P(A)P(B∣A)=P(B)P(A∣B)
例子:假设一个学校里有60%男生和4 0%女生.女生穿裤子的人数和穿裙子的人数相等,所有男生穿裤子.一个人在远处随机看到了一个穿裤子的学生.那么这个学生是女生的概率是多少?
P(女) = 0.4
P(裤子|女) = 0.5
P(裤子) = 0.6 + 0.2 = 0.8
P(女|裤子) = P(裤子|女) * P(女) / P(裤子) = 0.5 * 0.4 / 0.8 = 0.25
coding实现:
from sklearn import naive_bayes
model=naive_bayes.GaussianNB()
model.fit(x_train,y_train)
result=model.predict(x_test)
sklearn
模块提供了数据集划分的相关方法,使用不同数据集或训练集,达到提高分类可信度from sklearn.model_selection import train_test_split
训练输入,测试输入,训练输出,测试输出=train_test_split(数据集,输出集,test_size=测试集占比,random_state=随机种子)
from sklearn.model_selection import cross_val_score
指标值数组=cross_val_score(模型,输入集,输出集,cv=折叠数,scoring=指标名)
交叉验证精度指标:
1.精确度(accuracy):分类正确的样本 / 总样本数
2.查准率(precision_weighted):针对每一个类别,预测正确的样本数 / 预测出来的样本数
3.召回率(recall_weighted):针对每一个类别,预测正确的样本数 / 实际存在的样本数
4.f1得分(f1_weighted):2x查准率 x 召回率 / (查准率 + 召回率)
from sklearn.model_selection import cross_val_score
指标值数组=cross_val_score(模型,输入集,输出集,cv=折叠数,scoring=指标名)
交叉验证精度指标:
1.精确度(accuracy):分类正确的样本 / 总样本数
2.查准率(precision_weighted):针对每一个类别,预测正确的样本数 / 预测出来的样本数
3.召回率(recall_weighted):针对每一个类别,预测正确的样本数 / 实际存在的样本数
4.f1得分(f1_weighted):2x查准率 x 召回率 / (查准率 + 召回率)
在交叉验证过程中,针对每一次交叉验证,**计算所有类别的查准率、召回率或者f1得分,然后取各类别响应指标值的平均值,作为这一次交叉验证的评估指标,**然后再将所有交叉验证的评估指标以数组的形式返回给调用者