KNN的思想:
如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
(根据uniform计算时的分类)
不足之处:计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最邻近点。
由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
Knn模型的生成分为7个小步骤:
1)数据获取
2)数据处理(特征数据、标签数据、dataFrame合并、数据洗牌、对index排序、数据格式转换(DataFrame->np.array)、维度转换)
3)数据分割:训练集、测试集
4)算法选择:KNN分类
5)模型训练:使用训练集数据
6)模型评分:模型的准确都——测试集合数据
7)模型预测:使用测试集数据进行预测
数据获取与处理
使用sklearn提供的鸢尾花数据集做例子。
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split # 数据分割
from sklearn.neighbors import KNeighborsClassifier
from sklearn.utils import shuffle
# 数据加载
iris = load_iris() # 获取鸢尾花数据集
pd_data = pd.DataFrame(iris['data'], columns=iris['feature_names']) # 生成DataFrame
pd_data['label'] = iris['target'] # 在Dataframe中添加一列,列名为label,每一行的数值从iris['target']得到
df = shuffle(pd_data) # 数据打乱
df.reset_index(drop=True, inplace=True) # 索引重新排序
# print(df.head(10)) # 默认显示前10行
x = df.iloc[:, :4].values # 特征(dataframe的前四列)
y = np.ravel(df.iloc[:, 4:].values) # 标签(dataframe的最后一列), 拍平:多维转一维
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=6) # 测试集占比为20%
模型选择与调优
knn算法中最重要的有3个参数:K、P、Weight
·K是选择最近邻居的个数,K值越小,训练误差将会降低,但是同时也可能会使模型更容易过拟合。K值越大,训练误差将会增大(距离输入点较远的点都可能会产生影响)。最极端的情况就是当K的数值等于样本数,则完全没有分类能力。所以K值的选择就像是抛物线,最高和最低都不是最好,可以通过网格交叉验证的方式得到一个较好的K值
·P是距离度量的参数,这里的P是明可夫斯基距离的P。
当P等于1时,为曼哈顿距离;
当P等于2时,为欧式距离;
当P趋于∞时,为切比雪夫距离。
所以P值的选取,相当于是选择哪一个距离公式能对输入点与样本点之间距离进行更好的计算。
·Weight是权重,其中有‘distance’和‘uniform’两种方法的加权方向。(当K等于1时二者无差别)
假定K选择为3
uniform :不考虑距离的权重
distance:考虑距离的权重,
假设输入点到红球的距离为1,而到另外两个蓝三角形的距离分别为5和6,加权计算后红色赢。
所以不是数量最多的蓝色作为分类,而是考虑距离后的红色作为分类。
代码部分
# 如果参数范围选择过大,则会使无用的计算量增大
param_list = [{
"n_neighbors": list(range(3, 13)),
"weights": ['uniform', 'distance'],
"p": [i for i in range(1, 8)]
}]
# K的范围上限一般为总样本数的根号,P的范围上限为2*特征数
# 模型创建
knn_model = KNeighborsClassifier()
# 网格化(交叉网格验证参数组的参数,得到最优模型)----超参调试
grid = GridSearchCV(knn_model, param_list, cv=10)
grid.fit(x_train, y_train)
print(grid.best_estimator_)
print(grid.best_score_)
print(grid.best_params_)
结果为
KNeighborsClassifier(n_neighbors=10, p=6, weights='distance')
0.975
{'n_neighbors': 10, 'p': 6, 'weights': 'distance'}
通过网格交叉验证得到最优模型的参数,再用参数代回建立模型
model = KNeighborsClassifier(n_neighbors=10, p=6, weights='distance')
# 6.根据数据训练模型
knn.fit(x_train, y_train)
# 7.模型评分及测试
score = knn.score(x_test, y_test)
predict = knn.predict(x_test)
print(predict == y_test)
模型的保存与调用
import joblib
joblib.dump(value=model, filename='KnnModelIrisClassify.model')
"""
1、创建一组新数据
2、加载模型
3、使用模型对数据进行分类
"""
model = joblib.load('KnnModelMovieClassify.model')
data = np.array([43, 3, 8])
print(data, data.shape)
data = data.reshape(1, -1) # 拍平转换为二维数组
print(data, data.shape)
print(model.predict(data))