原理:
KNN 算法也叫K近邻算法。假设给定一个训练数据集,其中的实例类别已定。它是通过找到一个数据集中与目标数据最近的K个邻居,然后通过多数表决等方式来预测目标数据的分类结果进行预测。
三要素:
距离度量、K值、分类决策规则
功能:
KNN算法是一种基于实例的学习算法,不需要对数据进行建模,因此非常适合用于分类和回归问题。它也是监督学习方法里的一种常用方法。
主要实现步骤:
计算测试数据与各训练数据之间的距离。
按照距离的大小进行排序。
选择其中距离最小的k个样本点。
确定K个样本点所在类别的出现频率。
返回K个样本点中出现频率最高的类别作为最终的预测分类。
对癌症肿瘤进行预测
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter # 为了做投票
# raw_data_x属于特征值,分别属于患病时间和肿瘤大小
raw_data_x = [[3.3935, 2.3312],
[3.1101, 1.7815],
[1.3438, 3.3684],
[3.5823, 4.6792],
[2.2804, 2.8670],
[7.4234, 4.6965],
[5.7451, 3.5340],
[9.1722, 2.5111],
[7.7928, 3.4241],
[7.9398, 0.7916]]
# raw_data_y属于目标值,0代表良性肿瘤,1代表恶性肿瘤
row_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
class KNNClassifier:
def __init__(self, k):
assert k > 1, "K值必须大于1"
self.k = k
self.x_train = None
self.y_train = None
def fit(self, x_train, y_train):
"""根据训练数据集x_train和y_train训练分类器
x_train: 训练数据的特征
y_train: 训练数据的目标
"""
assert x_train.shape[0] == y_train.shape[0], "x_train的大小必须等于y_train的大小"
assert self.k <= x_train.shape[0], "x_train的大小必须大于K"
self.x_train = x_train
self.y_train = y_train
def euc_dis(self, instance1, instance2):
"""
计算两个样本instance1和instance2之间的欧式距离
instance1: 第一个样本, array型
instance2: 第二个样本, array型
"""
dist = np.sqrt(sum((instance1 - instance2) ** 2))
return dist
def knn_classify(self, testInstance):
"""
给定一个测试数据testInstance, 通过KNN算法来预测它的标签。
testInstance: 测试数据,这里假定一个测试数据为array型
"""
distances = [self.euc_dis(x, testInstance) for x in self.x_train]
kneighbors = np.argsort(distances)[:self.k]
count = Counter(self.y_train[kneighbors])
return count.most_common()[0][0]
def score(self, x_test, y_test):
"""根据测试样本x_test进行预测,和真实的目标值y_test进行比较,计算预测结果的准确度"""
predictions = [self.knn_classify(x) for x in x_test]
correct = np.count_nonzero((predictions == y_test) == True)
return float(correct)/len(x_test)
def __repr__(self):
return "KNN(k={})".format(self.k)
if __name__ == "__main__":
# 从数据集中选择2个样本为测试样本, 其余的均为训练样本
x_train = np.array(raw_data_x[:-2])
y_train = np.array(row_data_y[:-2])
x_test = np.array(raw_data_x[-2:])
y_test = np.array(row_data_y[-2:])
knn = KNNClassifier(3)
knn.fit(x_train, y_train)
score = knn.score(x_test, y_test)
print("测试精确度为: %.3f" % score)
# 未知的待分类样本
x_test2 = np.array([8.9093, 3.3657])
result = knn.knn_classify(x_test2)
if result == 0: result = "良性肿瘤"
else: result = "恶性肿瘤"
print("对[8.9093, 3.3657]的预测结果为:【%s】" % result)
结果: