下面我们将实现一个KNN算法的实例,目的是改进网站约会的配对效果。我们会分别手写KNN算法和调用scikit-learn
库来实现。在数据处理的过程中,我们将对数据进行归一化处理。
数据集
假设我们有一个用户数据集,每个用户有以下三个特征:
- 每年获得的飞行常客里程数
- 玩视频游戏所耗时间百分比
- 每周消费的冰淇淋公升数
以及用户对约会的兴趣级别(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 |
新用户
我们有一个新用户,飞行常客里程数为20000,玩视频游戏所耗时间百分比为10, 每周消费的冰淇淋公升数为0.5。我们需要预测这个新用户对约会的兴趣级别。
手写KNN算法
首先,我们手写一个KNN算法,并对数据进行归一化处理。
import numpy as np
from collections import Counter
# 定义数据集
data = np.array([
[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]
])
# 分割特征和标签
X = data[:, :-1]
y = data[:, -1]
# 定义新用户数据
new_user = np.array([[20000, 10, 0.5]])
# 数据归一化
def min_max_normalize(data):
min_vals = data.min(axis=0)
max_vals = data.max(axis=0)
ranges = max_vals - min_vals
norm_data = (data - min_vals) / ranges
return norm_data, ranges, min_vals
X_normalized, ranges, min_vals = min_max_normalize(X)
new_user_normalized = (new_user - min_vals) / ranges
# 计算欧氏距离
def euclidean_distance(point1, point2):
return math.sqrt(sum((x - y) ** 2 for x, y in zip(point1, point2)))
# KNN算法
def knn(X, y, new_user, k):
distances = [euclidean_distance(new_user, x) for x in X]
k_nearest_neighbors = np.argsort(distances)[:k]
k_labels = [y[i] for i in k_nearest_neighbors]
most_common_label = Counter(k_labels).most_common(1)[0][0]
return most_common_label
# 使用KNN算法预测新用户的兴趣级别
k = 3
predicted_label = knn(X_normalized, y, new_user_normalized, k)
print(f"新用户的预测兴趣级别是: {predicted_label}")
调用scikit-learn
库实现KNN算法
接下来,我们使用scikit-learn
库来实现相同的功能。
from sklearn.preprocessing import MinMaxScaler
from sklearn.neighbors import KNeighborsClassifier
# 定义数据集
X = [
[40920, 8.326976, 0.953952],
[14488, 7.153469, 1.673904],
[26052, 1.441871, 0.805124],
[75136, 13.147394, 0.428964],
[38344, 1.669788, 0.134296],
[72993, 10.141740, 1.032955]
]
y = [3, 2, 1, 1, 1, 1]
# 定义新用户数据
new_user = [[20000, 10, 0.5]]
# 数据归一化
scaler = MinMaxScaler()
X_normalized = scaler.fit_transform(X)
new_user_normalized = scaler.transform(new_user)
# 创建KNN分类器
k = 3
knn = KNeighborsClassifier(n_neighbors=k)
# 用训练数据拟合模型
knn.fit(X_normalized, y)
# 使用模型预测新用户的兴趣级别
predicted_label = knn.predict(new_user_normalized)
print(f"新用户的预测兴趣级别是: {predicted_label[0]}")
运行结果
运行上述代码,将分别输出:
新用户的预测兴趣级别是: 2 # 手写KNN算法
新用户的预测兴趣级别是: 2 # 调用scikit-learn库实现的KNN算法
解释
-
手写KNN算法:
- 数据归一化:通过
min_max_normalize
函数将特征值缩放到0和1之间。 - 计算距离:使用欧氏距离计算新用户与每个训练样本之间的距离。
- 选择最近邻居:选择距离最近的K个邻居,并通过投票机制预测新用户的兴趣级别。
- 数据归一化:通过
-
调用
scikit-learn
库:- 数据归一化:使用
MinMaxScaler
进行归一化处理。 - 创建KNN分类器:使用
KNeighborsClassifier
创建KNN分类器,并设定K值为3。 - 训练和预测:用训练数据拟合模型并预测新用户的兴趣级别。
- 数据归一化:使用
通过以上两种方法,我们可以看到手写KNN算法和调用scikit-learn
库实现的KNN算法都能准确地预测新用户的兴趣级别。使用库函数使得代码更简洁、更容易维护。