(二)机器学习---K近邻算法(KNN)

r囧r小猫 2022-12-26 15:21 282阅读 0赞

目录

    • 一:K邻近算法介绍:
      • 1:欧拉距离:
      • 2:使用K邻近算法实现分类:
      • 3: sklearn中knn算法的应用:
      • 4:自己写代码模拟KNN算法(了解):
    • 二:划分数据集:
      • 1:自己模拟实现:
      • 2:封装成工具类:
      • 3:使用sklearn中的train_test_split:
    • 三:划分精确度:
      • 1:自己实现:
      • 2:封装成工具类使用:
      • 3:直接调用sklearn中的accuracy_score进行划分:
    • 四:超参数:
      • 1:超参数概念:
      • 2:代码实现寻找最优K值:
      • 3:K近邻算法的优化:
    • 五:归一化:
      • 1:为什么要归一化:
      • 2:归一化的方式?
      • 3:代码实现归一化:
      • 4:sklearn中的归一化:

一:K邻近算法介绍:

  • 1:首先要有原始已知标签的数据。
  • 2:把需要预测的点和所有已知的点计算距离。
  • 3:找到和待遇测点最近的K个点。
  • 4:根据K个点的标签确定待测点的标签。
  • KNN算法可以做回归问题,也可以做分类问题。
  • knn算法没有得到模型,它是机器学习中唯一一个不需要训练过程的算法。

1:欧拉距离:

在这里插入图片描述

2:使用K邻近算法实现分类:

1:准备特征值和标签值:

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. # 1:定义特征值位置
  4. raw_data_x=[[3.3144558 , 2.33542461],
  5. [3.75497175, 1.93856648],
  6. [1.38327539, 3.38724496],
  7. [3.09203999, 4.47090056],
  8. [2.58593831, 2.13055653],
  9. [7.41206251, 4.80305318],
  10. [5.912852 , 3.72918089],
  11. [9.21547627, 2.8132231 ],
  12. [7.36039738, 3.35043406],
  13. [7.13698009, 0.40130301]]
  14. # 2:定义特征值的属性(0,1是上面标签的类别)
  15. raw_data_y=[0,0,0,0,0,1,1,1,1,1]
  16. # 3:转换成numpy的多维数组
  17. X_train = np.array(raw_data_x)
  18. y_train = np.array(raw_data_y)

2:验证多维数组的方法:
在这里插入图片描述

3:利用matplotlib绘制图像:

  1. #利用matplotlib绘制图像
  2. plt.scatter(X_train[y_train==0,0],X_train[y_train==0,1],color='g')
  3. plt.scatter(X_train[y_train==1,0],X_train[y_train==1,1],color='r')
  4. plt.show()

在这里插入图片描述
4:加入预测点,再次绘制图像:

  1. # 创建预测点数组
  2. x=np.array([8.093607318,3.365731514])
  3. plt.scatter(X_train[y_train==0,0],X_train[y_train==0,1],color='g')
  4. plt.scatter(X_train[y_train==1,0],X_train[y_train==1,1],color='r')
  5. # 将预测点加入图中
  6. plt.scatter(x[0],x[1],color='b')
  7. plt.show()

在这里插入图片描述
5:实现距离计算:

  1. from math import sqrt # 开根号的函数
  2. # 1: 现在X_train二维数组中,取出每个的一维数组
  3. # 一维数组和一维数组之间可以直接相减 x_train - x 即:[3.3144558 , 2.33542461] - [8.093607318,3.365731514]
  4. # **2 指的是将差值的一维数组,每个数都平方操作。
  5. # np.sum(平方后的一维数组)就是一维数组求和
  6. # sqrt(数):就是求出的最后的开平方后的和
  7. # 最后拿到的数据是个数组,就是各个点到预测点的距离。
  8. distances = [sqrt(np.sum((x_train-x)**2)) for x_train in X_train]
  9. print(distances)
  10. # 对计算的距离进行排序:根据数值进行排序,返回的是排序后的下标
  11. nearest = np.argsort(distances)
  12. # 打印下标
  13. print(nearest)

在这里插入图片描述
6:定义k值,得出计算结果:

  1. k=6
  2. # 获取距离最近的前k个数据的下标,拿到的是最近的6个数的便签值。
  3. topK_y = [y_train[i] for i in nearest[:k]]
  4. #统计每个y值出现的次数
  5. from collections import Counter
  6. # 拿到的是值与数量的字典
  7. votes = Counter(topK_y)
  8. print(votes) # Counter({1: 5, 0: 1})
  9. #获取出现次数最多的那个y的取值
  10. print(votes.most_common(1)) # [(1, 5)],返回一个数组,先按频数排序,如果频率相同,则按照字母排序。
  11. predict_y = votes.most_common(1)[0][0] # 取出数组的第一个元祖的,元祖第一个位置(key)
  12. print(predict_y)# 这个就应该是该元素的便签值

3: sklearn中knn算法的应用:

1:安装sklearn :
在这里插入图片描述
2:使用sklearn进行预测:
在这里插入图片描述

  1. # 1: 导包
  2. from sklearn.neighbors import KNeighborsClassifier
  3. #2:创建knn算法的分类器实例,选取最近的6个点
  4. knn_classifier = KNeighborsClassifier(n_neighbors=6)
  5. #拟合训练数据
  6. knn_classifier.fit(X_train,y_train)
  7. #将样本维度变为二维,因为我训练的维度就是二维的。
  8. x1 = x.reshape(1, -1)
  9. #利用knn算法进行预测
  10. y_predict = knn_classifier.predict(x1)
  11. #得出预测结果
  12. y_predict[0]
  13. # 输出 1

4:自己写代码模拟KNN算法(了解):

1:自己定义一个KNN算法:

  1. import numpy as np
  2. from math import sqrt
  3. from collections import Counter
  4. class KNNClassifier:
  5. def __init__(self, k):
  6. """初始化kNN分类器"""
  7. assert k >= 1, "k must be valid"
  8. self.k = k
  9. self._X_train = None
  10. self._y_train = None
  11. def fit(self, X_train, y_train):
  12. """根据训练数据集X_train和y_train训练kNN分类器"""
  13. assert X_train.shape[0] == y_train.shape[0], \
  14. "the size of X_train must be equal to the size of y_train"
  15. assert self.k <= X_train.shape[0], \
  16. "the size of X_train must be at least k."
  17. self._X_train = X_train
  18. self._y_train = y_train
  19. return self
  20. def predict(self, X_predict):
  21. """给定待预测数据集X_predict,返回表示X_predict的结果向量"""
  22. assert self._X_train is not None and self._y_train is not None, \
  23. "must fit before predict!"
  24. assert X_predict.shape[1] == self._X_train.shape[1], \
  25. "the feature number of X_predict must be equal to X_train"
  26. y_predict = [self._predict(x) for x in X_predict]
  27. return np.array(y_predict)
  28. def _predict(self, x):
  29. """给定单个待预测数据x,返回x的预测结果值"""
  30. assert x.shape[0] == self._X_train.shape[1], \
  31. "the feature number of x must be equal to X_train"
  32. distances = [sqrt(np.sum((x_train - x) ** 2))
  33. for x_train in self._X_train]
  34. nearest = np.argsort(distances)
  35. topK_y = [self._y_train[i] for i in nearest[:self.k]]
  36. votes = Counter(topK_y)
  37. return votes.most_common(1)[0][0]
  38. def __repr__(self):
  39. return "KNN(k=%d)" % self.k

2:将kNN.py文件放入到和jupyter的代码相同的目录下,在jupyter中利用魔法方法进行代码运行。

  1. #利用魔法方法加载kNN.py文件
  2. %run knn/kNN.py
  3. #创建实例
  4. knn_clf = KNNClassifier(k=6)
  5. #拟合训练集
  6. knn_clf.fit(X_train,y_train)
  7. #预测输入样例
  8. y_predict = knn_clf.predict(x1)
  9. #得出预测结果
  10. y_predict[0]

二:划分数据集:

  • 一般要将数据集划分成测试集和训练集。
  • 训练集参与模型训练,测试集不参与模型训练,只用作评估。一般2/8分。

1:自己模拟实现:

1: 加载数据:

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from sklearn import datasets

2: 获取特征值和目标值:

  1. #获取sklearn中的内置数据集
  2. iris = datasets.load_iris()
  3. print(iris.data) # 获取特征值(多维数组)
  4. print(iris.target)# 获取标签值(目标值,一维数组)

在这里插入图片描述
3:划分测试集和训练集:

思路:1:先求测试集/训练集的长度,根据长度生成随机的一个列表。
2:根据随机比例,和训练集长度,将列表划分成两部分,一部分存储的是训练集的下标,另一部分存储的是测试集的下标。
3:然后根据这个列表,划分测试集和训练集。

  1. X = iris.data
  2. y = iris.target
  3. # 1:将长度X对应的索引值进行随机排列,返回的是打乱顺序的列表。
  4. shuffle_indexes = np.random.permutation(len(X))
  5. #2: 定义测试机的比例
  6. test_ratio = 0.2
  7. #3: 得到测试集对应的数据量
  8. test_size = int(len(X) * test_ratio)
  9. #4:获取测试集的索引和训练集的索引
  10. test_indexes = shuffle_indexes[:test_size] # 测试集的索引
  11. train_indexes = shuffle_indexes[test_size:]# 训练集的索引
  12. #获取训练数据集
  13. X_train = X[train_indexes]
  14. y_train = y[train_indexes]
  15. #获取测试数据集
  16. X_test = X[test_indexes]
  17. y_test = y[test_indexes]

2:封装成工具类:

1:C:\Users\11737\knn,在knn文件夹中创建model_selection.py文件,文件中存入这些内容:

  1. import numpy as np
  2. def train_test_split(X, y, test_ratio=0.2, seed=None):
  3. """将数据 X 和 y 按照test_ratio分割成X_train, X_test, y_train, y_test"""
  4. assert X.shape[0] == y.shape[0], \
  5. "the size of X must be equal to the size of y"
  6. assert 0.0 <= test_ratio <= 1.0, \
  7. "test_ration must be valid"
  8. if seed:
  9. np.random.seed(seed)
  10. shuffled_indexes = np.random.permutation(len(X))
  11. test_size = int(len(X) * test_ratio)
  12. test_indexes = shuffled_indexes[:test_size]
  13. train_indexes = shuffled_indexes[test_size:]
  14. X_train = X[train_indexes]
  15. y_train = y[train_indexes]
  16. X_test = X[test_indexes]
  17. y_test = y[test_indexes]
  18. return X_train, X_test, y_train, y_test

2: C:\Users\11737\knn中新建_init_.py文件,使其变为工程目录,以便于后面能够直接导入train_test_split方法。
在这里插入图片描述
3:测试封装后的代码:

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from sklearn import datasets
  4. #获取sklearn中的内置数据集
  5. iris = datasets.load_iris()
  6. X = iris.data # 特征值
  7. y = iris.target # 目标值
  8. from knn.model_selection import train_test_split # 导入自己封装的函数
  9. X_train,X_test,y_train,y_test = train_test_split(X,y)# 分好数据集和测试集
  10. from knn.kNN import KNNClassifier # 导入训练模型
  11. knn_clf = KNNClassifier(k=6) # 创建对象
  12. knn_clf.fit(X_train,y_train) # 训练
  13. y_predict = knn_clf.predict(X_test) # 测试集进行预测

在这里插入图片描述

3:使用sklearn中的train_test_split:

  1. from sklearn.model_selection import train_test_split
  2. X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)

三:划分精确度:

1:自己实现:

1: 加载数据:
在这里插入图片描述
2:拿出一个数据测试:
在这里插入图片描述
在这里插入图片描述
3:使用KNN算法进行预测:

  1. from knn.model_selection import train_test_split
  2. X_train,X_test,y_train,y_test = train_test_split(X,y,test_ratio=0.2) # 使用我们自己的对测试集进行划分
  3. from knn.kNN import KNNClassifier
  4. knn_clf = KNNClassifier(k=6) # 构造模型
  5. knn_clf.fit(X_train,y_train) # 进行训练
  6. y_predict = knn_clf.predict(X_test) # 进行预测
  7. sum(y_predict == y_test)/y_test.shape[0] # 计算准确率

在这里插入图片描述

2:封装成工具类使用:

1:计算精确度的代码进行封装:
新建一个文件专门用来计算精确度:C:\Users\11737\knn
在这里插入图片描述
2:kNN.py创建一个方法,直接能调用这个方法,得到准确率:

  1. def score(self, X_test, y_test):
  2. """根据测试数据集 X_test 和 y_test 确定当前模型的准确度"""
  3. y_predict = self.predict(X_test)
  4. return accuracy_score(y_test, y_predict)

3: 进行测试:

  1. knn_clf.score(X_test,y_test)

3:直接调用sklearn中的accuracy_score进行划分:

  1. from sklearn.model_selection import train_test_split
  2. from sklearn.neighbors import KNeighborsClassifier
  3. #划分数据集
  4. X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
  5. #训练knn模型
  6. knn_classifier = KNeighborsClassifier(n_neighbors=6)
  7. knn_classifier.fit(X_train,y_train)
  8. #预测测试集
  9. y_predict = knn_classifier.predict(X_test)
  10. #计算准确率
  11. from sklearn.metrics import accuracy_score
  12. # 使用accuracy_score
  13. accuracy_score(y_test,y_predict)

四:超参数:

1:超参数概念:

在这里插入图片描述

2:代码实现寻找最优K值:

1: 先用一个随机的K测试:

  1. import numpy as np
  2. import matplotlib
  3. import matplotlib.pyplot as plt
  4. from sklearn import datasets
  5. digits = datasets.load_digits()
  6. X = digits.data
  7. y = digits.target
  8. from sklearn.model_selection import train_test_split
  9. from sklearn.neighbors import KNeighborsClassifier
  10. X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
  11. knn_classifier = KNeighborsClassifier(n_neighbors=6)
  12. knn_classifier.fit(X_train,y_train)
  13. #得到评分数据
  14. knn_classifier.score(X_test,y_test)

得到的准确率是:0.9888888888888889

2:寻找最优K:

  1. best_score = 0.0
  2. best_k = -1
  3. for k in range(1,11):
  4. knn_classifier = KNeighborsClassifier(n_neighbors=k)
  5. knn_classifier.fit(X_train,y_train)
  6. score = knn_classifier.score(X_test,y_test)
  7. print("k={}, score={}".format(k, score))
  8. if score > best_score:
  9. best_k = k
  10. best_score = score
  11. print("best_k =",best_k)
  12. print("best_score =",best_score)

在这里插入图片描述
在这里插入图片描述

3:K近邻算法的优化:

1: 存在的问题:
在这里插入图片描述
在这里插入图片描述
2:在sklearn的官方问题中存在此问题的具体实现,参数weights默认为uniform,不考虑距离,如传入distance,则考虑距离。

  1. best_score = 0.0
  2. best_k = -1
  3. for method in ["uniform","distance"]:
  4. for k in range(1,11):
  5. knn_classifier = KNeighborsClassifier(n_neighbors=k,weights=method)
  6. knn_classifier.fit(X_train,y_train)
  7. score = knn_classifier.score(X_test,y_test)
  8. if score > best_score:
  9. best_k = k
  10. best_score = score
  11. best_method = method
  12. print("best_method =",best_method)
  13. print("best_k =",best_k)
  14. print("best_score =",best_score)

在这里插入图片描述
注意第二次的时候,只考虑距离,跟数值就没关系了,即使个数很多,我们也要选择距离近的那个。

五:归一化:

1:为什么要归一化:

问题:我们有两个样本,每个样本有两个特征,一个是肿瘤大小,一个是肿瘤的发现时间。

在这里插入图片描述

2:归一化的方式?

1:最值归一化:
在这里插入图片描述
2:均值方差归一化:
在这里插入图片描述

3:代码实现归一化:

1: 一维数组最值归一化:
在这里插入图片描述
2:二维数组归一化:
在这里插入图片描述
3:均值方差归一化:

  1. #随机生成shape为(50,2)数值范围在0-100范围内的二维数组
  2. X2 = np.random.randint(0,100,(50,2))
  3. #转换为float类型
  4. X2 = np.array(X2,dtype=float)
  5. #对两个样本进行均值方差归一化
  6. X2[:,0] = (X2[:,0]-np.mean(X2[:,0]))/np.std(X2[:,0])
  7. X2[:,1] = (X2[:,1]-np.mean(X2[:,1]))/np.std(X2[:,1])

在这里插入图片描述

4:sklearn中的归一化:

1: 数据的准备:

  1. import numpy as np
  2. from sklearn import datasets
  3. iris = datasets.load_iris()
  4. X = iris.data
  5. y = iris.target
  6. # 划分训练集和测试集
  7. from sklearn.model_selection import train_test_split
  8. X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,test_size=0.2,random_state=1)

2:进行归一化处理:

  1. # 进行均值方差归一化处理
  2. from sklearn.preprocessing import StandardScaler
  3. # 1:创建对象
  4. ss = StandardScaler()
  5. # 2:学习均值和方差
  6. ss.fit(X_train,y_train)
  7. print(ss.mean_)# 内部的均值
  8. print(ss.scale_) # 内部的方差
  9. #3:转换训练集和测试集
  10. X_train1 = ss.transform(X_train)
  11. X_test1 = ss.transform(X_test)

3: 对归一化和没有归一化的进行测试:
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,282人围观)

还没有评论,来说两句吧...

相关阅读

    相关 [机器学习] k-近邻算法(knn)

    最近在参加大数据的暑期培训,记录一下学习的东西。   引言   懒惰学习法:简单的存储数据,并且一直等待,直到给定一个检验数据,才进行范化,以便根据与存储的训练元组的相似