KNN用于回归问题
KNN不仅可以用于分类问题,也可以用回归问题。
主要算法思路就是:使用KNN计算某个数据点的预测值时,模型从训练数据集中选择离该数据点最近的k个数据点,并且把这些数据的y值取均值,把求出的这个均值作为新数据点的预测值。
实验数据集
data.csv:
数据是csv格式的,第一行是标签。
python代码实现
以下代码在dataTransform函数里改一下数据集,可以直接在pycharm中运行
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler, StandardScaler# KNN核心算法
def classify(inX, dataSet, y_train, k):m, n = dataSet.shape # shape(m, n)测试集中有m个个体和n个特征# 计算测试数据到每个点的欧式距离distances = []for i in range(m):sum = 0for j in range(n):sum += (inX[j] - dataSet[i][j]) ** 2distances.append(sum ** 0.5)sortDist = sorted(distances) # 得到的是按照distance排序好的# 求k个最近的值的平均值sum = 0 for i in range(k):sum += y_train[distances.index(sortDist[i])]return sum/k# 用于归一化
x_scaler = MinMaxScaler(feature_range=(-1, 1))
y_scaler = MinMaxScaler(feature_range=(-1, 1))# 数据的读取和归一化
def dataTransform():df = pd.read_csv('data.csv', encoding='utf-8')x = df[['AVGACURATE', 'AVGSPEED', 'AVGHEADDIST', 'LIGHTVEH', 'LONGVEH', 'HUGEVEH', 'MIDVEH', 'MINIVEH']]y = df['AVGFLOW']y = y.values.reshape(-1, 1) # 在sklearn中,所有的数据都应该是二维矩阵,所以需要使用.reshape(1,-1)进行转换# 对数据进行最大最小值归一化x = x_scaler.fit_transform(x)y = y_scaler.fit_transform(y)# 训练集x_train = x[0:1000, :] # 二维y_train = y[0:1000]# 测试集x_test = x[1001:1292, :]y_test = y[1001:1292]return x_train, y_train, x_test, y_test# 测试算法
def Test():x_train, y_train, x_test, y_test = dataTransform()predict = [] # 记录预测值err = 0for i in range(len(x_test)): # 对每一个测试数据predict.append(classify(x_test[i], x_train, y_train, 5)) # 返回平均值# print(predict[i], y_test[i])err += np.square(y_test[i]-predict[i]) # 计算误差和mse_err = err/len(x_test)print("the total mse error is: ", mse_err)predict = np.array(predict) # 转成arraydraw(predict, y_test)# 画图函数
def draw(predict, y_test):# 先转化为实际值predict = predict.reshape(-1, 1)predict = y_scaler.inverse_transform(predict)y_test = y_scaler.inverse_transform(y_test)# 解决中文无法显示的问题plt.rcParams['font.sans-serif'] = [u'SimHei']plt.rcParams['axes.unicode_minus'] = Falseplt.figure(figsize=(8, 6))plt.plot(predict, label='pred')plt.plot(y_test, label='actual')plt.title('车流预测_测试集', )plt.legend()plt.show()if __name__ == '__main__':Test()