目前我们训练数据的过程:将所有的数据都作为训练数据,训练出一个模型,每当得到一个新的数据,则计算新数据到训练数据的距离,预测得到新数据的类别。
比如:银行发放信用卡,银行要想得到客户的信用等级,需要跟踪用户两三年时间来收集用户信息,才能得到,如果我们将两三年的数据全部作为训练集,当新客户来临时,我们又需要等待两三年,才能知道新用户的真实label,所以在短期内很难根据真实label判断模型好坏,进而无法改进模型。
将所有数据集全部用于训练,这种做法是不可取的。
那我们该怎么做呢?
将数据中的70%-80%作为训练数据,将剩余的作为测试数据,训练数据用于训练模型,测试数据用于判断模型好坏。
将数据集进行切分,可以用 sklearn 中的 train_test_split()方法。
import numpy as np
from collections import Counter
from sklearn.neighbors import KNeighborsClassifier
class ProKNNClassifier(object):
def __init__(self, raw_x, raw_y, k, test_ratio=0.3, seed=None):
if len(raw_x) != len(raw_y):
print(f'特征值与目标值的长度应该相等')
return
if k > len(raw_y) and isinstance(k, int):
print(f'k应该小于y并且是数字类型')
return
x_train, x_test, y_train, y_test = self.split_data(raw_x, raw_y, test_ratio, seed)
self.train_x = np.array(x_train)
self.train_y = np.array(y_train)
self.predict_x = np.array(x_test)
self.expire = y_test
self.k = k
def count_predict(self):
'''实现原理'''
# 计算点与点之间的距离
distances = np.sum(np.square(self.train_x - self.predict_x), axis=1)
# 对计算的距离进行排序
nearest = np.argsort(distances)
# 获取距离最近的前k个数据
top_k = [self.train_y[i] for i in nearest[:self.k]]
# 统计每个y值出现的次数
votes = Counter(top_k)
# 获取出现次数最多的那个y的取值
predict_y = votes.most_common(1)[0][0]
# 打印
print(predict_y)
def split_data(self, raw_x, raw_y, test_ratio, seed):
if seed:
np.random.seed(seed)
# 将长度x对应的索引值进行随机排列
shuffle_indexes = np.random.permutation(len(raw_x))
# 得到数据集对应的数据量
test_size = int(len(raw_x) * test_ratio)
# 获取测试集的索引和训练集的索引
test_indexes = shuffle_indexes[:test_size]
train_indexes = shuffle_indexes[test_size:]
# 获取训练数据集和对应的特征值
x_train = np.array(raw_x)[train_indexes]
y_train = np.array(raw_y)[train_indexes]
# 获取测试数据集
x_test = np.array(raw_x)[test_indexes]
y_test = np.array(raw_y)[test_indexes]
return x_train, x_test, y_train, y_test
def train(self):
'''knn算法 在 sklearn 中的使用方法'''
# 创建knn算法的分类器实例
knn_classifier = KNeighborsClassifier(n_neighbors=self.k)
# 拟合训练数据
knn_classifier.fit(self.train_x, self.train_y)
# 利用knn进行预测
sum = len(self.predict_x)
right = 0
for index, i in enumerate(self.predict_x):
# 将样本维度变为二维
x1 = i.reshape(1, -1)
y_predict = knn_classifier.predict(x1)
# 得出预测结果
predict = y_predict[0]
expire = self.expire[index]
if predict == expire:
right += 1
# 统计预测正确率
result = right / sum
print(result, sum, right)
if __name__ == '__main__':
# 定义特征值
raw_x = [[3.3144558, 2.33542461],
[3.75497175, 1.93856648],
[1.38327539, 3.38724496],
[3.09203999, 4.47090056],
[2.58593831, 2.13055653],
[7.41206251, 4.80305318],
[5.912852, 3.72918089],
[9.21547627, 2.8132231],
[7.36039738, 3.35043406],
[7.13698009, 0.40130301]]
# 定义目标值
raw_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
# 定义k值
k = 6
knn = ProKNNClassifier(raw_x, raw_y, k)
knn.train()