k近邻算法(knn)
-
k近邻算法原理:
存在一个样本数据集合(训练样本集),并且样本集中的每个数据都存在标签。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据的(最近邻)的分类标签,作为新数据的分类。一般只选取样本集中最相似的前k个数据。k一般是不大于20的整数。
-
优缺点
- 优点:精度高,对异常值不敏感,无数据输入假定。
- 缺点:计算复杂度高,空间复杂度高。
- 使用数据范围:数值型和标称型(数值型例如0.1具体值,标称型是指真或假)
-
特征距离计算(距离计算方法有很多,这里先列三种)
- 欧氏距离
d [ X n 1 , X n 2 ] = ∑ i = 1 n ( X i 1 − X i 2 ) 2 d[X_{n}^{1}, X_{n}^{2}] = \sqrt{\sum_{i=1}^{n}(X_{i}^{1}-X_{i}^{2})^{2}} d[Xn1,Xn2]=i=1∑n(Xi1−Xi2)2 - 曼哈顿距离
d [ X n 1 , X n 2 ] = ∑ i − 1 n ∣ X i 1 − X i 2 ∣ d[X_{n}^{1}, X_{n}^{2}] = \sum_{i-1}^{n}\left | X_{i}^{1}-X_{i}^{2} \right | d[Xn1,Xn2]=i−1∑n∣∣Xi1−Xi2∣∣ - 切比雪夫距离
d [ X n 1 , X n 2 ] = m a x ( ∣ X 1 1 − X 1 2 ∣ , ∣ X 2 1 − X 2 2 ∣ , . . . . . . ∣ X n 1 − X n 2 ∣ ) d[X_{n}^{1}, X_{n}^{2}] = max(\left | X_{1}^{1}-X_{1}^{2} \right |,\left | X_{2}^{1}-X_{2}^{2} \right |,......\left | X_{n}^{1}-X_{n}^{2} \right |) d[Xn1,Xn2]=max(∣∣X11−X12∣∣,∣∣X21−X22∣∣,......∣∣Xn1−Xn2∣∣)
- 欧氏距离
-
简单例子(电影类型)
根据欧氏距离计算公式,算出未知电影与已知电影类型之间的距离。
电影名称 | 打斗镜头 | 接吻镜头 | 电影类型 | 欧式距离 |
---|---|---|---|---|
1 | 3 | 104 | 爱情片 | 20.5 |
2 | 2 | 100 | 爱情片 | 18.7 |
3 | 1 | 81 | 爱情片 | 19.2 |
4 | 101 | 10 | 动作片 | 115.3 |
5 | 99 | 5 | 动作片 | 117.4 |
6 | 98 | 2 | 动作片 | 118.9 |
? | 18 | 90 | 未知 | — |
根据欧式距离我们可以对电影按照距离大小进行排序,假定K=3,则最近邻的三个电影分别是电影2,电影3,电影1,这三种电影的列别都是爱情片,所以我们可以认为未知电影的类型也是爱情片。
- k近邻算法的一般流程
(1)收集数据:可以使用任意方法
(2)准备数据:计算距离所需要的数值
(3)分析数据:可以使用任何方法
(4)训练数据:k近邻算法不需要进行训练
(5)测试算法:计算错误率(选取不在数据集中的已知类别的数据进行测试)
(6)使用算法。 - python 实现knn算法 改进约会网站的配对效果
约会数据实例(1-不喜欢的人 2-魅力一般的人 3-极具魅力的人):
每年飞行里程数 | 每天游戏视频耗费时间百分比 | 每周消费冰激凌公升数 | 交往类型 |
---|---|---|---|
40920 | 8.326976 | 0.953952 | 3 |
14488 | 7.153469 | 1.673904 | 2 |
26052 | 1.441871 | 0.805124 | 1 |
75136 | 13.147394 | 0.428964 | 1 |
38344 | 1.669788 | 0.134296 | 1 |
72993 | 10.141740 | 1.032955 | 1 |
… | … | … | … |
- 第一步:准备数据,从文本中读取数据
@tools.funcRunTime def load_data(file_path): try: feature = [] label = [] with open(file_path) as f: for line in f: feature_temp = [] line = [float(i) for i in line.strip().split()] feature_temp.append(line[0:3]) abel.append(int(line[-1])) feature.extend(feature_temp) return np.mat(feature), label except Exception as msg: tools.printInfo(2, msg) sys.exit()
- 准备数据:归一化数值(减少因为数值原因影响分类结果)
@tools.funcRunTime def normalization_data(feature): try: # 计算特征的均值和标准差 feature_u = feature.mean(axis=0) feature_sigma = np.std(feature, axis=0) # 计算特征矩阵的大小 feature_size = np.shape(feature) feature_u = feature_u.repeat(feature_size[0], axis=0) feature_sigma = feature_sigma.repeat(feature_size[0], axis=0) # 归一化 feature = (feature - feature_u) / feature_sigma return feature except Exception as msg: tools.printInfo(2, msg) sys.exit()
- 实现算法
def knn(unknown_data, feature, feature_u, feature_sigma, label): try: # 未知数据归一化 unknown_data = (unknown_data - feature_u) / feature_sigma feature_size = np.shape(feature) # 未知数据与已知数据的距离 unknown_data = unknown_data.repeat(feature_size[0], axis=0) unknown_data = unknown_data - feature unknown_data = np.multiply(unknown_data, unknown_data) unknown_data = np.sum(unknown_data, axis=1) unknown_data = np.sqrt(unknown_data) # 未知数据距离排序取前五的类别 unknown_data = [i[0] for i in unknown_data.tolist()] k_label = [i[0] for i in sorted(enumerate(unknown_data), key=lambda x:x[1])] k_label = k_label[0:5] k_label = [label_data[i] for i in k_label] return k_label except Exception as msg: tools.printInfo(2, msg) sys.exit()
- 上述代码以及数据在github的地址为:
https://github.com/xzccfzy/knn.git