了解sklearn库的第一步就是训练感知器,下面通过实例来演示,具体实现步骤如下。
(1)把150个鸢尾花样本的花瓣长度和花瓣宽度存入特征矩阵 X ,把相应的品种分类标签存入向量 y :
from sklearn import datasets import numpy as np iris=datasets.load_iris() X= iris.data[:,[2,3]] y= iris.target print('Class labels:',np.unique(y)) Class labels:[0 1 2]
(2)为了评估经过训练的模型对未知数据处理的效果,再进一步将数据集分裂成单独的训练集和测试集:
from sklearn.model_selection import train_test_split #train_test_split函数把X和y随机分为30%的测试数据和70%的训练数据 #在分割前已经在内部训练,random_state为固定的随机数种子,确保结果可 #重复,通过定义stratify=y获得内置的分层支持,将各子数据集中不同分类标签 #的数据比例设置为总数据集比例 X_train,X_test,y_train,y_test=train_test_split( X,y,test_size=0.3,random_state=1,stratify=y)
(3)调用NumPy的bincount函数来对阵列中的每个值进行统计,以验证数据。
#计算每种标签的样本数量有多少,分别是50个 print('y的标签计数:',np.bincount(y)) #计算训练集中每种标签样本数量有多少,分别是35个 print('y_train的标签计数:',np.bincount(y_train)) #计算测试集中每种标签样本数量有多少,分别是15个 print('y_test的标签计数:',np.bincount(y_test)) y的标签计数:[50 50 50] y_train的标签计数:[35 35 35] y_test的标签计数:[15 15 15]
(4)调用sklearn库中预处理模块preprocessing中的类StanderScaler来对特征进行标准化:
#对特征进行标准化 from sklearn.preprocessing import StandardScaler sc=StandardScaler() sc.fit(X_train) X_train_std= sc.transform(X_train) X_test_std=sc.transform(X_test)
在以上代码中,调用StanderScaler的fit方法对训练数据的每个特征维度参数 μ 和 σ 进行估算。调用transform方法,利用估计的参数 μ 和 σ 对训练数据进行标准化。
注意: 在标准化测试集时,要注意使用相同的特征调整参数以确保训练集与测试集的数值具有可比性。
(5)训练感知器模型。
from sklearn.linear_model import Perceptron ppn=Perceptron(max_iter=40,eta0=0.1,random_state=1) ppn.fit(X_train_std,y_train) Perceptron(alpha=0.0001,class_weight=None,eta0=0.1,fit_intercept=True, max_iter=40,n_iter=None,n_jobs=1,penalty=None,random_state=1, shuffle=True,tol=None,verbose=0,warm_start=False)
(6)调用predict方法做预测。
y_pred=ppn.predict(X_test_std) print('错误分类的样本:%d'%(y_test!=y_pred).sum())
此处结果为“错误分类的样本:3”,当然也有其他的性能指标,如分类准确度:
#计算分类准确度 from sklearn.metrics import accuracy_score print('准确性:%.2f'%accuracy_score(y_test,y_pred))
此处结果为“准确性:0.93”。
(7)利用plot_decision_regions函数绘制新训练感知器的模型决策区,并以可视化的方式展示区分不同花朵样本的效果,可以通过圆圈来突出显示来自测试集的样本:
from matplotlib.colors import ListedColormap from matplotlib import pyplot as plt plt.rcParams['font.sans-serif']=['SimHei'] #显示中文 plt.rcParams['axes.unicode_minus'] = False #显示负号 def plot_decision_regions(X,y,classifier,test_idx=None,resolution=0.02): #setup marker generator and color map markers =('s','x','o','^','v') colors =('red','blue','lightgreen','gray','cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) #绘制决策面 x1_min,x1_max = X[:,0].min()- 1,X[:,0].max()+ 1 x2_min,x2_max = X[:,1].min()- 1,X[:,1].max()+ 1 xx1,xx2 = np.meshgrid(np.arange(x1_min,x1_max,resolution), np.arange(x2_min,x2_max,resolution)) Z = classifier.predict(np.array([xx1.ravel(),xx2.ravel()]).T) Z = Z.reshape(xx1.shape) plt.contourf(xx1,xx2,Z,alpha=0.3,cmap=cmap) plt.xlim(xx1.min(),xx1.max()) plt.ylim(xx2.min(),xx2.max()) for idx,cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl,0], y=X[y == cl,1], alpha=0.8, c=colors[idx], marker=markers[idx], label=cl, edgecolor='black') #突出显示测试样本 if test_idx: #绘制所有样本 X_test,y_test=X[test_idx,:],y[test_idx] plt.scatter(X_test[:,0], X_test[:,1], #将测试集数据显示为粉色标记 c='pink', edgecolor='black', alpha=1.0, linewidth=1, marker='o', s=100, label='测试集') X_combined_std=np.vstack((X_train_std,X_test_std)) y_combined=np.hstack((y_train,y_test)) plot_decision_regions(X=X_combined_std,y=y_combined, classifier=ppn,test_idx=range(105,150)) plt.xlabel('花瓣长度[标准化]') plt.ylabel('花瓣宽度[标准化]') plt.legend(loc='左上角') plt.tight_layout() plt.show()
运行程序,效果如图3-1所示。
图3-1 绘制新训练感知器的模型决策区
如图3-1中所看到的,三种花不能被线性决策边界完全分离,所以实践中通常不推荐使用感知器算法。
逻辑回归一般用于估计某种事物的可能性(“可能性”而非数学上的“概率”),不可以直接当作概率值来用。逻辑回归可以用于预测系统或产品的故障的可能性,还可用于市场营销应用程序,例如预测客户购买产品或中止订购的倾向等。在经济学中它可以用来预测一个人选择进入劳动力市场的可能性,而商业应用则可以用来预测房主拖欠抵押贷款的可能性。还可以根据逻辑回归模型,预测在不同的自变量情况下,发生某种情况的概率。
逻辑回归是一种分类模型而非回归模型,在介绍逻辑回归前先来了解几个相关定义。
(1)让步比:
,代表阳性事件的概率,它指的是要预测的事件的可能性,例如:病人有某种疾病的可能性、某人买彩票中了的可能性等。
(2)让步比的对数形式:
。logit函数输入值的取值范围在0到1之间,转换或计算的结果值为整个实数范围,可以用它来表示特征值和对数概率之间的线性关系:
此处, p ( y =1| x )是某个特定样本属于 x 类给定特征标签为1的条件概率。
(3)sigmoid函数:
,它是logit函数的逆形式。sigmoid函数的形状如图3-2所示。
图3-2 sigmoid函数的形状
在建立逻辑回归模型时,想要最大化 L 的可能性,先要假设数据集中的样本都是相互独立的个体。公式如下:
在实践中,最大化该方程的自然对数,也被称为对数似然函数:
用梯度下降方法最小化代价函数 J :
为更好地理解这个代价函数,计算一个样本训练实例的代价如下:
J ( ϕ ( z ), y ; w )=- y log( ϕ ( z ))-(1- y )log(1- ϕ ( z ))
从方程中可以看到,如果 y =0,第一项为0,如果 y =1,第二项为0:
下面代码实现绘制一张图,用于说明 ϕ ( z )不同样本实例分类的代价:
import numpy as np from matplotlib import pyplot as plt def cost_1(z): return - np.log(sigmoid(z)) def cost_0(z): return - np.log(1 - sigmoid(z)) z = np.arange(-10,10,0.1) phi_z = sigmoid(z) c1 = [cost_1(x)for x in z] plt.plot(phi_z,c1,label='J(w)if y=1') c0 = [cost_0(x)for x in z] plt.plot(phi_z,c0,linestyle='--',label='J(w)if y=0') plt.ylim(0.0,5.1) plt.xlim([0,1]) plt.xlabel('$\phi$(z)') plt.ylabel('J(w)') plt.legend(loc='best') plt.tight_layout() plt.show()
运行程序,效果如图3-3所示。
图3-3 不同样本实例分类的代价
由结果可得出结论:如果分类为1,则概率越小表示分类错误程度越高;如果分类为0,则概率越大表示分类错误程度越高。
【例3-1】 用sklearn训练逻辑回归模型。
from sklearn.linear_model import LogisticRegression lr=LogisticRegression(C=100.0,random_state=1) lr.fit(X_train_std,y_train) plot_decision_regions(X_combined_std,y_combined, classifier=lr,test_idx=range(105,150)) plt.xlabel('花瓣长度[标准化]') plt.ylabel('花瓣宽度[标准化]') plt.legend(loc='左上角') plt.tight_layout() plt.show()
运行程序,效果如图3-4所示。
图3-4 sklearn训练逻辑回归模型效果
什么是过拟合?什么是欠拟合?过拟合是指模型在训练数据上表现良好,但无法概括未见过的新数据或测试数据;欠拟合是指模型不足以捕捉训练数据中的复杂模式,因此对未见过的数据表现不良。图3-5可以很好地阐明过拟合与欠拟合的情况。
图3-5 过拟合与欠拟合
正则化又是什么?正则化是处理共线性(特征之间的高相关性),消除数据中的噪声,并最终能避免过拟合的非常有效的方法。正则化的逻辑是引入额外偏置来惩罚极端的权重。
最常见的正则化是L2正则化,具体如下:
其中, λ 为正则化参数。
逻辑回归的代价函数可以通过增加一个简单的正则项来调整,这将在模型训练的过程中缩小权重:
可通过绘制两个权重系数的L2正则化路径实现可视化,代码如下:
weights,params=[],[] for c in np.arange(-5,5): lr = LogisticRegression(C=10. * * c,random_state=1) lr.fit(X_train_std,y_train) weights.append(lr.coef_[1]) params.append(10. * * c) weights = np.array(weights) plt.plot(params,weights[:,0], label='花瓣长度') plt.plot(params,weights[:,1],linestyle='--', label='花瓣宽度') plt.ylabel('权重系数') plt.xlabel('C') plt.legend(loc='左上角') plt.xscale('log') plt.show()
运行程序,效果如图3-6所示。
图3-6 两个权重系数的L2正则化
如图3-6所示,减小逆正则化参数C可以增大正则化的强度,权重系数会变小。