python代码实现KNN暴力算法,难点在于循环计算每个预测点、循环计算每个特征数据。以后需要优化。
from sklearn.datasets import load_iris
import pandas as pd
import numpy as np
# print set
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)
def load_data():
# 导入鸢尾花数据集
iris = load_iris()
# 鸢尾花特征数据和类别数据合并
df_data = pd.DataFrame(iris.data, columns=iris.feature_names)
df_target = pd.Series(iris.target)
df_target.name = 'class'
df_train_ = pd.concat([df_data, df_target], axis=1, sort=False)
# 创建预测数据
df_predict_ = pd.DataFrame(np.arange(12).reshape((3, 4)), columns=iris.feature_names)
return df_train_, df_predict_
# 只判断一行预测数据的类型
def get_max_po_class(df_train, df_predict, k):
class_dic = {} # 存放最大可能类别的频率
distinct = []
feature_list = df_predict.columns.to_list() # 预测数据的特征名称
# 对训练数据的每一行分别计算其与预测数据的欧氏距离
for row in range(df_train.shape[0]):
d = 0
for feature in feature_list:
d = np.square(abs(df_train.loc[row][feature] - df_predict[feature])) + d
distinct.append(np.sqrt(d[0]))
s_distinct = pd.Series(distinct) # 所有训练数据和预测数据的欧氏距离
s_distinct.name = 'distinct'
df_class = pd.concat([df_train['class'], s_distinct], axis=1) # 合并类别和距离序列
df_class.sort_values(['distinct'], ascending=True, inplace=True) # 距离升序排序
df_class_2 = df_class.head(k)['class'].value_counts() # 取前k项类别并计数
max_po_class = df_class_2.idxmax() # 计数最大的即为预测数据最有可能属于的类别
class_dic[max_po_class] = df_class_2.max() / k # 计算最可能类别的频率
return max_po_class, class_dic
# 主函数,主要是对每个预测数据都进行预测
def main(df_train, df_predict, k):
for row in range(df_predict.shape[0]):
max_po_class, class_dic = get_max_po_class(df_train, df_predict, k)
print(max_po_class)
print(class_dic)
if __name__=='__main__':
k = 5 # 近邻数量
df_train, df_predict = load_data()
main(df_train, df_predict, k)