本文代码及数据集来自《Python大数据分析与机器学习商业案例实战》
K近邻算法分类模型将离待预测样本点最近的K个训练样本点中出现次数最多的分类作为待预测样本点的分类,K近邻算法回归模型则将离待预测样本点最近的K个训练样本点的平均值作为待预测样本点的分类。
案例一
# 1.读取数据
import pandas as pd
df = pd.read_excel('手写字体识别.xlsx')
print(df.head())
运行结果:
# 2.提取特征变量和目标变量
X = df.drop(columns='对应数字')
y = df['对应数字']
'''
#所有样本的1×1024矩阵都由0和1构成,故无须做标准化处理。如果在其他场景中出现数量级相差较大的特征变量,则需要对数据进行标准化处理
from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(X)
'''
# 3.划分训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)
# 4.模型搭建
from sklearn.neighbors import KNeighborsClassifier as KNN
knn = KNN(n_neighbors=5)
knn.fit(X_train, y_train)
# 5.模型预测 - 预测数据结果
y_pred = knn.predict(X_test)
print(y_pred[0:100])
a = pd.DataFrame() # 创建一个空DataFrame
a['预测值'] = list(y_pred)
a['实际值'] = list(y_test)
print(a.head())
#评分方法一
from sklearn.metrics import accuracy_score
score = accuracy_score(y_pred, y_test)
print(score)
#评分方法二
score = knn.score(X_test, y_test)
print(score)
运行结果:
得分:0.9819121447028424
前面搭建模型时设置n_neighbors参数为5,如果想换成其他数值进行参数调优,可以使用交叉验证和网格搜索来完成,代码如下。
from sklearn.model_selection import GridSearchCV
parameters = {'n_neighbors' : [1, 2, 3, 4, 5, 6, 7, 8, 9]}
knn = KNN()
grid_search = GridSearchCV(knn, parameters, cv=5)
grid_search.fit(X_train, y_train)
print(grid_search.best_params_['n_neighbors'])
案例二
Pillow库是一款功能强大、简单好用的第三方图像处理库,可以通过“pip install pillow”命令进行安装。
from PIL import Image
img = Image.open('数字4.png')
img = img.resize((32,32)) #调整为32×32像素
# 图片灰度处理
img = img.convert('L')
img.show()
运行结果:
# 图片二值化处理
import numpy as np
img_new = img.point(lambda x: 0 if x > 128 else 1)
arr = np.array(img_new)
for i in range(arr.shape[0]):
print(arr[i])
如下图所示是将图片格式的数字4转换成由0和1组成的“新的数字4”。将色彩数值大于128的像素点赋值为0,反之赋值为1。图像在进行灰度处理后,每一个像素点由一个取值范围为0~255的数字表示,其中0代表黑色,255代表白色。arr.shape获取的是数组的行数和列数,arr.shape[0]对应行数,arr.shape[1]则对应列数。
运行结果:
这是一个32×32的矩阵,数字1代表有颜色的地方,数字0代表无颜色的地方,这样就完成了手写数字识别的第一步也是最关键的一步:将图片转换为计算机能识别的内容——数字0和1,这个步骤又称为图像二值化。上面获得的32×32的二维数组不能用于数据建模,因此还需要用reshape(1,-1)函数将其转换成一行(若写成reshape(-1,1)则转换成一列),即1×1024的一维数组,代码如下。
# 二维数组转一维数组
arr_new = arr.reshape(1, -1)
print(arr_new)
print(arr_new.shape) #打印出arr_new行列数
经过图像二值化处理获得的32×32的0-1矩阵相当于一个二维数组,为了方便进行机器学习建模,还需要对这个二维数组进行简单的处理:在第1行数字之后依次拼接第2~32行的数字,得到一个1×1024的一维数组。运行结果:
把处理好的一维数组arr_new传入前面训练好的knn模型中。
answer = knn.predict(arr_new)
print('图片中的数字为:' + str(answer[0]))
提取出的元素是数字,不能直接进行字符串拼接,所以用str()函数转换后再进行字符串拼接。预测结果为4。