使用scikit-learning 实现机器学习分类算法
分类算法的选择
没有免费的午餐理论:没有任何一种分类器可以在所有可能的应用场景下都有良好的表现。
实践证明,只有比较了多种学习算法的性能,才能为特定问题挑选出最合适的模型。这些模型针对不同数量的特征或样本、数据集中噪声的数量,以及类别是否线性可分等问题时,表现各不相同。
总而言之,分类器的性能、计算能力和预测能力,在很大程度上都依赖于用于模型训练的相关数据。训练机器学习算法所涉及的五个主要步骤可概述如下:
1.特征的选择
2.确定性能评价标准
3.选择分类器及其优化算法
4.对模型性能的评估
5.算法的调优
初涉scikit-learn的使用
使用scikit-learn训练感知器
import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.cross_validation import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import Perceptron from sklearn.metrics import accuracy_score iris=datasets.load_iris() X=iris.data[:,[2,3]] y=iris.target X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=0) sc=StandardScaler() sc.fit(X_train) X_train_std=sc.transform(X_train) X_test_std=sc.transform(X_test) ppn=Perceptron(n_iter=40,eta0=0.1,random_state=0) ppn.fit(X_train_std,y_train) y_pred=ppn.predict(X_test_std) print('Misclassified samples:%d'%(y_test!=y_pred).sum()) print('Accuracy:%.2f'%accuracy_score(y_test,y_pred))
使用scikit-learn中cross_validation模块中的train_test_split函数,随机将数据矩阵X与类标向量y按照3:7的比例分为测试数据集(45个样本)和训练数据集(105个样本)。
为了优化性能,许多机器学习和优化算法都要求对数据做特征缩放。在此,我们将使用scikit-learn的preprocessing模块中的StandardScaler类对特征进行标准化处理。使用StandardScaler中的fit方法,可以计算训练数据中每个特征的平均值和方差。通过通用transform方法,可以使用前面计算得到的平均值和方差来对训练数据做标准化处理。需注意的是,我们要使用相同的缩放参数分别处理训练和测试数据集,以保证它们的值是彼此相当的。
对于使用scikit-learn的接口训练感知器,其流程与我们在(二)中实现的感知器的流程类似:在加载了linear_model模块中的Perceptron类后,我们实例化一个新的Perceptron对象,并通过fit方法训练模型。此模型中的参数eta0与我们自行实现的感知器中的学习率eta等价,而参数n_iter定义了迭代的次数
使用scikit-learn完成模型的训练后,就可以在测试数据集上使用predict方法进行预测了
在metrics模块中,scikit-learn还实现了许多不同的性能矩阵。accuracy_score(y_test,y_pred)
逻辑斯蒂回归中的类别概率
感知器是机器学习分类算法中优雅易用的一个入门算法,不过其最大的缺点在于:在样本不是完全线性可分的情况下,它永远不会收敛。上一小节中关于分类的任务就是这样的一个例子。直观上,可以把原因归咎于:在每次迭代过程中,总是存在至少一个分类错误的样本,从而导致了权重持续更新。当然,你也可以改变学习速率并增加迭代次数,不过感知器在此类数据集上仍旧永远无法收敛。为了提高分类的效率,我们学习另外一种针对线性二分类别分类问题的简单但更高效的算法:逻辑斯蒂回归。请注意:不要被其名字所迷惑,逻辑斯蒂回归是一个分类模型,而不是回归模型。
sigmoid函数的图
import numpy as np from sklearn.linear_model import LogisticRegression def sigmoid(z): return 1.0/(1+np.exp(-z)) z=np.arange(-7,7,0.1) phi_z=sigmoid(z) plt.plot(z,phi_z) plt.axvline(0.0,color='k') plt.axhspan(0.0,1,facecolor='1.0',alpha=1.0,ls='dotted') plt.axhline(y=0.5,ls='dotted',color='k') plt.yticks([0.0,0.5,1.0]) plt.ylim(-0.1,1.1) plt.xlabel('z') plt.ylabel('$phi (z)$') plt.show()
from sklearn.linear_model import LogisticRegression用来调用逻辑斯蒂回归模型,我们用fit方法训练数据。
使用支持向量机最大化分类间隔
一种强大且广发应用的学习算法是支持向量机(SVM),它可以看作对感知器的扩展。在感知器算法中,我们可以最小化分类误差。而在SVM中,我们的优化目标是最大化分类间隔。此外间隔是指两个分离的超平面(决策边界)间的距离,而最靠近超平面的训练样本称作支持向量。
import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import SGDClassifier from sklearn.svm import SVC from matplotlib.colors import ListedColormap def plot_decision_region(X,y,classifier,test_idx=None,resolution=0.02): 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.4,cmap=cmap) plt.xlim(xx1.min(),xx1.max()) plt.ylim(xx2.min(),xx2.max()) X_test,y_test=X[test_idx,:],y[test_idx] for idx,cl in enumerate(np.unique(y)): plt.scatter(x=X[y==cl,0],y=X[y==cl,1],alpha=0.8,c=cmap(idx),marker=markers[idx],label=cl) if test_idx: X_test,y_test=X[test_idx,:],y[test_idx] plt.scatter(X_test[:.0],X_test[:,1],c='',s=55,label='test set') ppn=SGDClassifier(loss='perceptron') lr=SGDClassifier(loss='log') svm=SGDClassifier(loss='hinge') np.random.seed(0) X_xor=np.random.randn(200,2) y_xor=np.logical_xor(X_xor[:,0]>0,X_xor[:,1]>0) y_xor=np.where(y_xor,1,-1) plt.scatter(X_xor[y_xor==1,0],X_xor[y_xor==1,1],c='b',marker='x',label='1') plt.scatter(X_xor[y_xor==-1,0],X_xor[y_xor==-1,1],c='r',marker='s',label='-1') plt.ylim(-3,0) plt.legend() plt.show() svm=SVC(kernel='rbf',random_state=0,gamma=0.1,C=10) svm.fit(X_xor,y_xor) plot_decision_region(X_xor,y_xor,classifier=svm) plt.legend(loc='upper left') plt.show()