监督学习和非监督学习
我们谈起机器学习经常会听到监督学习和非监督学习,它们的区别在哪里呢?监督学习是有标签的,而非监督学习是没有标签的。比如有一批酒,我们知道里面包括红酒和白酒,算法f可以用于鉴别某一个酒是否为红酒和白酒,这时候算法f就称作为监督学习,红酒、白酒即为标签。如果现在另有一批酒,我们知道里面包括不同品种的酒,但是不知道有几类,算法g可以把相同类别的酒归为一类,不同类别的酒归为不同的类(比如:红酒、白酒、啤酒、米酒…), 算法g就称作为非监督学习。在监督学习中我们称作“分类”,在非监督学习中我们称作“聚类”。本文提到的K邻近算法属于监督学习内的“分类”算法。
分类和回归算法
分类问题用于分类型数据,比如红酒、白酒、啤酒、米酒;回归问题用于连续的数值型数据,比如股票的走势。K邻近算法用KNeighborsClassifier类实现分类算法,用KNeighborsRegressor实现回归算法。
K邻近算法实现分类问题
在上图(a)中已经知道有2个分类,红色与黑色,现在有一个新的节点(绿色),我们判断这个点属于红色还是绿色。K邻近算法的核心思想是寻找与这个点最近的点。比如绿色的点为A(x1,y1), 已知的点为B(xi,yi),最近的点即为(xi-x1)2+(yi-y1)2最小,即方差最小或欧式空间最小。现在我们指定最近邻数为k,k=1(上图(b)),这是找到一个红点离它最近,所以把这个绿点认为属于红色。但是当最近邻数设为k=3(上图(c)),有一个红点离它最近,两个黑点离它最近,把这个绿点认为属于黑色。由此可以看出,在K邻近算法中最近邻数设置不同,会影响最后的结果。
看下面代码
# coding:utf-8 # 导入数据集生成器 from sklearn.datasets import make_blobs # 导入KNN分类器 from sklearn.neighbors import KNeighborsClassifier # 导入画图工具 import matplotlib.pyplot as plt # 导入数据划分模块、分为训练集和测试集 from sklearn.model_selection import train_test_split def sklearn_base(): # 产生200个新样本,分成2类,随机生成器的种子为8 data = make_blobs(n_samples=200,centers=2, random_state=8) X,y =data print("X is :",X) print("y is :",y) #将数据集用散点图方式进行可视化分析 plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.spring,edgecolor='k') plt.show()
使用make_blobs类设置200个新样本,分成2类,然后以散点图方式可视化如下:
这两类数据分别为紫色和黄色。
输出:
X is : [[ 6.75445054 9.74531933] [ 6.80526026 -0.2909292 ] [ 7.07978644 7.81427747] … y is : [0 1 0 1 0 0 1 0 0 1 1 1 0 0 1 1 0 0 1 0 0 1 1 0 1 0 1 1 1 0 1 1
由于X是一个矩阵,表示数据,y是一个向量,表示属于哪个类。所以X一般为大写,y一般为小写
接下来我们绘制紫色区域和黄色区域,并且看看一个点(6.75,4.82)属于哪个紫色还是黄色?
#加载KNeighborsClassifier clf = KNeighborsClassifier() clf.fit(X,y) #下面代码用于画图 x_min,x_max = X[:,0].min()-1,X[:,0].max()+1 y_min,y_max = X[:,1].min()-1,X[:,1].max()+1 #生成网格点坐标矩阵 xx,yy = np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02)) #预测数据集X的结果 Z = clf.predict(np.c_[xx.ravel(),yy.ravel()]) Z = Z.reshape(xx.shape) #绘制分类图 plt.pcolormesh(xx, yy, Z,shading='auto',cmap=plt.cm.Spectral) plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.spring,edgecolor='k') #设置或查询 x 轴限制 plt.xlim(xx.min(),xx.max()) #设置或查询 y 轴限制 plt.ylim(yy.min(),yy.max()) #设置图的标题 plt.title("Classifier:KNN") plt.scatter(6.75,4.82,marker='*',c='red',s=200紫色和黄色为代测试分类的点 plt.show() print('[6.75,4.82]属于分类:',clf. predict([[6.75,4.82]]))
输出:
[6.75,4.82]属于分类:[1]
即黄色,图为:
图中待测的点通过函数plt.scatter内的marker='*' ,c='red'以红五星呈现(marker默认为'o',即圆点)。(在Python的机器学习中函数的参数很多,我们不用全部记住,记住重要的几个参数即可)。
上面仅仅以两类的分类,下面我们来看看多个类的分类。
def sklearn_multivariate(): data2 = make_blobs(n_samples=500,centers=5, random_state=8) X2,y2 =data2 plt.scatter(X2[:,0],X2[:,1],c=y2,cmap=plt.cm.spring,edgecolor='k') plt.show()
现在有500个样本,分为5类make_blobs(n_samples=500,centers=5…),如下图所示:
我们通过颜色的差异可以看到这五类数据,其中有两类(黄色和橙色有些合为一起)。我们画出它的区域图,并且查看它的准确率。
clf = KNeighborsClassifier() clf.fit(X2,y2) x_min,x_max = X2[:,0].min()-1,X2[:,0].max()+1 y_min,y_max = X2[:,1].min()-1,X2[:,1].max()+1 xx,yy = np.meshgrid(np.arange(x_min,x_max,.02), np.arange(y_min,y_max,.02))#生成网格点坐标矩阵 Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])#预测数据集X的结果 Z = Z.reshape(xx.shape) plt.pcolormesh(xx, yy, Z,shading='auto',cmap=plt.cm.Spectral)#绘制分类图 plt.scatter(X2[:,0],X2[:,1],c=y2,cmap=plt.cm.spring,edgecolor='k') plt.xlim(xx.min(),xx.max())#设置或查询 x 轴限制 plt.ylim(yy.min(),yy.max())#设置或查询 y 轴限制 plt.title("Classifier:KNN") plt.show() print('模型正确率:{:.2f}'.format(clf.score(X2,y2)))
输出:
模型正确率:0.96
模型正确率:0.96(96%),说明成绩还是可以的。
K邻近算法实现回归问题
介绍了分类问题,我们来看一下K邻近算法实现分类问题。
#导入make_regression数据集成生成器 from sklearn.datasets import make_regression def sklearn_regression(): X,y = make_regression(n_features=1,n_informative=1,noise=50,random_state=8) #将数据集用散点图方式进行可视化分析 plt.scatter(X,y,c='orange',edgecolor='k') plt.show()
通过make_regression生成回归数据,并且仍旧通过plt.scatter方法以散点图方法显示。
reg = KNeighborsRegressor() # 用KNN模型拟合数据 reg.fit(X,y) # 把预测结果图像化 z = np.linspace(-3,3,200).reshape(-1,1) plt.scatter(X,y,c='orange',edgecolor='k') plt.plot(z,reg.predict(z),c='k',linewidth=3) plt.title("KNN Regressor") plt.show() print('模型正确率:{:.2f}'.format(reg.score(X,y)))
输出:
模型正确率:0.77
通过KNeighborsRegressor类的fit方法拟合数据,并且以折线方式显示出来。
这个时候。模型的正确率仅为0.77,拟合不好(我们从拟合折线也可以直观看出拟合不好)。在默认情况下,n_neighbors=5,我们下面把n_neighbors设置为2,看看拟合情况。
reg = KNeighborsRegressor(n_neighbors=2) reg.fit(X,y) z = np.linspace(-3,3,200).reshape(-1,1) plt.scatter(X,y,c='orange',edgecolor='k') plt.plot(z,reg.predict(z),c='k',linewidth=3) plt.title("KNN Regressor") plt.show() print('模型正确率:{:.2f}'.format(reg.score(X,y)))
输出:
模型正确率:0.86
拟合准确率提升到0.86,从图上我们也发现拟合程度比上次好。