导入依赖的库
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split #切分训练集和测试集
from sklearn.metrics import accuracy_score #计算分类预测的准确率
查看一些基本信息
iris = load_iris()
df = pd.DataFrame(data=iris['data'],columns=iris.feature_names) #加载数据和列名
df['class']=iris.target #添加一列
df['class'] = df['class'].map({0:iris.target_names[0],1:iris.target_names[1],2:iris.target_names[2]})
df.describe()
#取出相关的数据信息
x=iris.data
y=iris.target.reshape(-1,1)
#test_size指定测试集所占比例,也可以使用train_size
#y进行等比例分成测试集和训练集,这样不会出现相同的y大部分分到了一起的现象
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=35,stratify=y)
核心算法实现
#l1距离就是曼哈顿距离,没有平方和和根号,只是绝对值,l2距离就是欧氏距离
def l1_distance(a,b):
return np.sum(np.abs(a-b),axis=1)
def l2_distance(a,b):
return np.sqrt(np.sum((a-b)**2,axis=1))
#分类器的实现
class kNN():
# 定义一个初始化方法
def __init__(self,n_neighbors=1,dist_func=l1_distance):
self.n_neighbors=n_neighbors
self.dist_func=dist_func
#训练模型方法
def fit(self,x,y):
self.x_train=x
self.y_train=y
#模型预测方法
def predict(self,x):
#初始化预测分类数组
y_pred = np.zeros((x.shape[0],1),dtype=self.y_train.dtype)
#遍历输入的x数据点,取出每一个数据点的序号i和数据x_test
for i,x_test in enumerate(x):
#x_test每一个样本与所有训练集的数据计算距离
distances = self.dist_func(self.x_train,x_test)
#得到的距离按照由近到远排序,取出索引
nn_index=np.argsort(distances)
#选取最近的k个点,保存它们对应的分类的类别
nn_y=self.y_train[nn_index[:self.n_neighbors]].ravel()
#统计类别中出现概率最高的那个,赋值给y_pred[i]
y_pred[i]=np.argmax(np.bincount(nn_y))
return y_pred
简单测试
#定义一个knn实例
knn = kNN(n_neighbors=3)
#训练模型
knn.fit(x_train,y_train)
#传入测试数据做预测
y_pred = knn.predict(x_test)
#求出预测准确率
accuracy = accuracy_score(y_test,y_pred)
print("预测准确率:",accuracy)
得到的结果为
预测准确率: 0.9333333333333333
使用不同的损失函数和求取不同的k值查看对结果的影响
#定义一个knn实例
knn= kNN()
#训练模型
knn.fit(x_train,y_train)
#保存结果到一个list
result_list=[]
#针对不同的参数选取做预测
for p in [1,2]:
knn.dist_func=l1_distance if p==1 else l2_distance
#考虑不同的k取值,步长为2
for k in range(1,10,2):
knn.n_neighbors=k
#传入测试数据做预测
y_pred = knn.predict(x_test)
#求出预测准确率
accuracy = accuracy_score(y_test,y_pred)
result_list.append([k,'l1_distance' if p==1 else 'l2_distance',accuracy])
df = pd.DataFrame(result_list,columns=['k','距离函数','预测准确率'])
print(df)
结果为:
k 距离函数 预测准确率
0 1 l1_distance 0.933333
1 3 l1_distance 0.933333
2 5 l1_distance 0.977778
3 7 l1_distance 0.955556
4 9 l1_distance 0.955556
5 1 l2_distance 0.933333
6 3 l2_distance 0.933333
7 5 l2_distance 0.977778
8 7 l2_distance 0.977778
9 9 l2_distance 0.977778
可以看到k值并不是越大越好