书名《深入浅出python机器学习》 作者:段小手
KNN即 K-最近邻算法,是分类最简单的一个算法了,就是测算距离新数据点最近的 n 个点,看哪类占比最大,新数据点就是属于哪类,接下来我们用代码试试看
from sklearn.datasets import make_blobs
# make_blobs 是sklearn 自带的数据集生成器,可以设定样本数,
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
%matplotlib inline
#我们生成了200个样本,分成了两类
data = make_blobs(n_samples = 200,centers = 2,random_state = 8)
X,y = data
plt.figure(figsize=(10,8))
plt.scatter(X[:,0],X[:,1],c=y,cmap = plt.cm.spring,edgecolor = 'k')
plt.show()

image.png
现在我们调用一下KNN,看一下两类的界限在哪,假设有个新数据点为(6.7,4),可以看一下是分成哪类
import numpy as np
clf = KNeighborsClassifier()
# 可以调用参数 n_neighbors ,默认为5
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,0.02),
np.arange(y_min,y_max,0.02))
#给背景图加上小点,用来染色,因为点太多了,运行时间会延长
Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
#给背景图里的每个点进行分类
Z = Z.reshape(xx.shape)
plt.figure(figsize=(10,8))
plt.pcolormesh(xx,yy,Z,cmap = plt.cm.Pastel1)
plt.scatter(X[:,0],X[:,1],c=y,cmap = plt.cm.spring,edgecolor = 'k')
plt.scatter(6.7,4,marker = '*',s = 100)
plt.show()

image.png
很明显,新数据点是属于第一类。有兴趣的朋友可以改一下参数试试看结果是否会更改
上面只是两个类别,但实际工作中,我们更多的是分成多类,接下来试试多元分类
# 我们玩一下分成五类的
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()

image.png
再调用一下KNN,还是默认 n = 5
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()])
Z = Z.reshape(xx.shape)
plt.figure(figsize=(10,8))
plt.pcolormesh(xx, yy, Z, cmap = plt.cm.Pastel1)
plt.scatter(X2[:,0], X2[:,1], c = y2)
plt.title('KNN Classifier')
plt.show()

image.png
我们还可以看看拟合程度:
print('二分类得分:{:.3f}'.format(clf.score(X,y)))
print('多元分类得分:{:.3f}'.format(clf.score(X2,y2)))
二分类得分:1.000
多元分类得分:0.956
其实上面没有分训练集和测试集,做法是不当的
KNN也可以用于回归分析,但是调用的函数是不一样的,要调用KNeighborsRegressor
from sklearn.datasets import make_regression
X3, y3 = make_regression(n_features = 1, n_informative = 1, noise = 50, random_state = 8)
plt.figure(figsize = (10,8))
plt.scatter(X3, y3, c = 'orange', edgecolor = 'k')
plt.show()

image.png
# 导入用于回归分析的KNN
from sklearn.neighbors import KNeighborsRegressor
reg = KNeighborsRegressor()
reg.fit(X3,y3)
z = np.linspace(-3,3,100).reshape(-1,1)
plt.figure(figsize = (10,8))
plt.scatter(X3, y3, edgecolor = 'k')
plt.plot(z,reg.predict(z),lw = 3)
plt.title('KNN Regressor')
plt.show()
print('得分:{:.3f}'.format(reg.score(X3,y3)))

image.png
得分比较低,可以调一下参数,把 n 改成其他的
reg2 = KNeighborsRegressor(n_neighbors = 2)
reg2.fit(X3, y3)
z = np.linspace(-3,3,100).reshape(-1,1)
plt.figure(figsize = (10,8))
plt.scatter(X3, y3, edgecolor = 'k')
plt.plot(z,reg2.predict(z),lw = 3)
plt.title('KNN Regressor')
plt.show()
print('reg2得分:{:.3f}'.format(reg2.score(X3,y3)))

image.png
得分从 0.77上升到 0.86了
接下来进行一个实战:酒的分类,同样数据集也是 sklearn 自带的
from sklearn.datasets import load_wine
wine_data = load_wine()
from sklearn.model_selection import train_test_split
# 拆分训练集 和 测试集,25%的样本作为测试集
X_train,X_test,y_train,y_test = train_test_split(wine_data['data'],wine_data['target'],test_size = 0.25,random_state = 0)
print('X_train shape = {}'.format(X_train.shape))
print('X_test shape = {}'.format(X_test.shape))
print('y_train shape = {}'.format(y_train.shape))
print('y_test shape = {}'.format(y_test.shape))
from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors = 1)
clf.fit(X_train, y_train)
print('得分:{:.3f}'.format(clf.score(X_test, y_test)))
X_train shape = (133, 13)
X_test shape = (45, 13)
y_train shape = (133,)
y_test shape = (45,)
得分:0.756
从上面可以看出样本有13个特征,有75%是可以分类正确的,
假设现在有个新的数据,需要进行分类
import numpy as np
X_new = np.array([13.2,2.77,2.51,18.5,96.6,1.04,2.55,
0.57,1.47,6.2,10.5,3.33,820])
print('预测分类为{}'.format(clf.predict([X_new])))
预测分类为[2]
以上就是KNN的一些普通用法,下一章是线性回归,包括普通线性回归、岭回归和套索回归