%matplotlib inline
import numpy as np
import pandas as pd
#读取莺尾花数据集,head参数来指定标题的行。默认为0,如果没有标题则使用None。
data = pd.read_csv(r"iris.arff.csv", header=0)
#显示头几个数据
#data.head(5)
#显示尾部几个数据
#data.tail(5)
#随机抽取样本,默认抽取一条,可通过参数指定抽取样本数量
#data.sample(10)
#将类别文本映射成数值类型
data["class"]= data["class"].map({"Iris-virginica":0, "Iris-setosa":1, "Iris-versicolor":2})
#删除不需要的ID列
#data.drop("Id", axis=1, inplace=True)
#data.duplicated().any()
#len(data)
#删除重复数据
data.drop_duplicates(inplace=True)
len(data)
#查看各个类别的莺尾花各有多少个
data["class"].value_counts()
class KNN:
"""使用Python语言实现K邻近算法。(实现分类)"""
def __init__(self, k):
"""初始化方法
parameters:
------
k:int 邻居的个数
"""
self.k=k;
def fit(self, X, y):
"""训练方法
paremeters:
------
X:类似数数组类型,形状[样本数量,特征数量]
待训练的样本特征(属性)
y:类似数组类型,形状[样本数量]
每个样本的标签
"""
#将X装换成np。array数组类型
self.X=np.asarray(X)
self.y=np.asarray(y)
def predict(self, X):
"""根据参数传递的样本,对样本进行预测
paremeters:
------
X:类似数数组类型,形状[样本数量,特征数量]
待训练的样本特征(属性)
Return:
------
result:数组类型
预测的结果
"""
X=np.asarray(X)
result=[]
#对np.array进行遍历,每次取数组的一行(一个样本)
for x in X:
#对于测试集的每一个样本,依次与训练集中的所有样本求距离
dis=np.sqrt(np.sum((x-self.X)**2,axis=1))
#返回数组排序后,每个数据在原数组(未排序)中的索引
index=dis.argsort()
#进行截断,只取前k个数(取距离最近的k个元素的索引)
index=index[:self.k]
#返回数组中每个元素出现的次数,元素必须是非负的整数
count=np.bincount(self.y[index])
#返回np.array数组中,值最大的索引,该索引就是我们判断的类别
#最大元素的索引,就是出现最多次数的元素
result.append(count.argmax())
return np.asarray(result)
def predict2(self, X):
"""根据参数传递的样本,对样本进行预测(考虑权重)
paremeters:
------
X:类似数数组类型,形状[样本数量,特征数量]
待训练的样本特征(属性)
Return:
------
result:数组类型
预测的结果
"""
X=np.asarray(X)
result=[]
#对np.array进行遍历,每次取数组的一行(一个样本)
for x in X:
#对于测试集的每一个样本,依次与训练集中的所有样本求距离
dis=np.sqrt(np.sum((x-self.X)**2,axis=1))
#返回数组排序后,每个数据在原数组(未排序)中的索引
index=dis.argsort()
#进行截断,只取前k个数(取距离最近的k个元素的索引)
index=index[:self.k]
#返回数组中每个元素出现的次数,元素必须是非负的整数, 考虑权重为距离的倒数
count=np.bincount(self.y[index], weights=1/dis[index])
#返回np.array数组中,值最大的索引,该索引就是我们判断的类别
#最大元素的索引,就是出现最多次数的元素
result.append(count.argmax())
return np.asarray(result)
#提取每个类别的莺尾花数据
t0=data[data["class"]==0]
t1=data[data["class"]==1]
t2=data[data["class"]==2]
#对每个类别数据进行洗牌
t0=t0.sample(len(t0), random_state=0)
t1=t1.sample(len(t1), random_state=0)
t2=t2.sample(len(t2), random_state=0)
#构建测试集和训练集
train_X=pd.concat([t0.iloc[:40, :-1], t1.iloc[:40, :-1], t2.iloc[:40, :-1]], axis=0)
train_y=pd.concat([t0.iloc[:40,-1], t1.iloc[:40,-1], t2.iloc[:40,-1]], axis=0)
test_X=pd.concat([t0.iloc[40:, :-1], t1.iloc[40:, :-1], t2.iloc[40:, :-1]], axis=0)
test_y=pd.concat([t0.iloc[40:,-1], t1.iloc[40:,-1], t2.iloc[40:,-1]], axis=0)
#创建KNN对象,进行训练和测试
knn=KNN(k=3)
#进行训练
knn.fit(train_X,train_y)
#进行测试,获得测试结果
result=knn.predict(test_X)
display(result)
display(test_y)
display(np.sum((result==test_y)))
display(len(result))
#考虑权重 进行测试
result2=knn.predict2(test_X)
display(np.sum((result==test_y)))
import matplotlib as mpl
import matplotlib.pyplot as plt
#默认情况下,matplotlib不支持中文显示,需要进行设置
#设置字体为黑体,以支持中文显示
mpl.rcParams["font.family"]="SimHei"
#设置在中文字体时,能够正常的显示负号(-)
mpl.rcParams["axes.unicode_minus"]=False
#"Iris-virginica":0, "Iris-setosa":1, "Iris-versicolor":2
#设置画布的大小
plt.figure(figsize=(10,10))
#绘制训练集的数据
plt.scatter(x=t0["sepallength"][:40], y=t0["petallength"][:40], color="r",label="Iris-virginica")
plt.scatter(x=t1["sepallength"][:40], y=t1["petallength"][:40], color="g",label="Iris-setosa")
plt.scatter(x=t2["sepallength"][:40], y=t2["petallength"][:40], color="b",label="Iris-versicolor")
#绘制测试机数据
right=test_X[result==test_y]
wrong=test_X[result!=test_y]
plt.scatter(x=right["sepallength"], y=right["petallength"], color='c', label="right", marker="x")
plt.scatter(x=wrong["sepallength"], y=wrong["petallength"], color='m', label="wrong", marker=">")
plt.xlabel("花萼长度")
plt.ylabel("花瓣长度")
plt.title("KNN分类结果")
plt.legend(loc="best")
plt.show()
KNN代码
最新推荐文章于 2024-05-09 19:20:18 发布