这里面涉及到一些算法实现的包,比如得到的每个点,求距离后怎么处理的问题。
# 前面求欧氏距离就不赘述了,这里主要是补充一点求出结果后怎么处理的问题 nearest = np.argsort(distances) # 这里对每个距离进行排列,得出index # 假设K=6的话 topX = [y_train[i] for i in nearest[:k]] # y_train[i] 是标签,得到的是一个类别列表 # 下一步是求出类别列表中哪种类别是最多的 from collections import Counter votes = Counter(topX) # 这里Counter函数返回的是一个字典类型,每个类别对应的数量字典 votes.most_common(1)[0][0] # 字典中最多的一类是 most_common返回的是元组列表,参数1是最多的一类下面是用sklearn库来调用实现KNN算法
from sklearn.neighbors import KNeighborsClassifier Knn_classfier = KNeighborsClassifier(n_neighbors=6) # 这里的6即是K值 Knn_classfier.fit(X_train,y_train) # 第一个参数是训练数据集,第二个参数是标签向量 Knn_classfier.predict(x) # 这里x是输入的待预测的值,这是个向量判断机器学习算法的性能
shuffle_indexes = np.random.permutation(len(X)) # 随机生成len(X)个索引 test_ratio = 0.2 # 测试数据集比例 test_size = int(len(X) * test_ratio) test_indexes = shuffle_indexes[:test_size] train_indexes = shuffle_indexes[test_size:] X_train = X[train_indexes] # 训练数据集 y_train = y[train_indexes] X_test = X[test_indexes] # 测试数据集 y_test = y[test_indexes] """ 首先是训练训练数据集中的样本 然后对测试数据集进行预测 最后比对预测数据集中的label中一样的比例,来预测准确率 """ y_predict = Knn_classfier.predict(X_test) sum(y_predict == y_test)/len(y_test) # 计算准确率我们也可以使用sklearn中自带的训练数据集和测试数据集分离器
from sklearn.model_selection import train_test_split X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2) # 接下来的步骤同上接下来是一个例子,手写数字数据集
import matplotlib.pyplot as plt from sklearn import datasets digits = datasets.load_digits() X = digits.data y = digits.target X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2) # 分离测试数据集和训练数据集 # 接下来就是同上了,没有什么好说的 # 求准确度的有个可以调用的函数 from sklearn.metrics import accuracy_score accuracy_score(y_test,y_predict)下面引入超参数
这里的超参数,打个比方,K=3的情况,三个点,其中两个同类型的点距离测试值比较远,而另一个类型的点比较近,这种情况下,只是单一的考虑数量来决定该点是哪种类型,明显是不太妥当的,应该是适当的考虑一下权值,比如说把距离的倒数作为权值考虑进去,距离越大的权值越小
Knn_classfier = KNeighborsClassifier(n_neighbors=6, weights = ) # 这里可以选择uniform/distance """ 这里还有一点需要提出来的是,距离问题,之前我们提到的距离都是指欧拉距离,但是这是不严谨的, 准确的来说应该用明可夫斯基距离,当p=2时,明式距离才等于欧拉距离 """ Knn_classfier = KNeighborsClassifier(n_neighbors=6, weights = "distance", p = ?) # p可以不断取值来确定最大的准确度,这里要强调的是,只有weights = "distance",才能有p参数网格搜索(Grid Search)
param_grid = [ { "weight":["uniform"], "n_neighbors":[i for i in range(1,11)] }, { "weight":["distance"], "n_neighbors":[i for i in range(1,11)], "p":[i for i in range(1,6)] } ] from sklearn.model_selection import GridSearchCV knn_clf = KNeighborsClassifier() # 定义一个空的分类器 grid_search = GridSearchCV(knn_clf, param_grid) grid_search.fit(X_train, y_train) grid_search.best_params_ # 最佳参数以字典的形式返回给你 grid_search.best_score_ # 最佳参数对应的准确度 # 下面是怎么用这个分类器 knn_clf = grid_search.best_estimator_ # 这里返回的是最佳的分类器 knn_clf.predict(X_test) knn_clf.score(X_test, y_test) # 返回准确率 # 其实这里网格搜索可以选择并行处理来加快处理速度 grid_search = GridSearchCV(knn_clf, param_grid, n_jobs=m) # 这里的m是采用的m核处理,当m=-1时,是计算机所有的核都在处理这个问题数据归一化处理
对于一些数据,相差太大的话,在求距离的时候会有很多不便之处,比如坐标为(0.1,1000)和(0.5,1633)这样求距离的话,显然是不太合适的,所以需要对数据进行处理,这里一般的处理方式是 Xscale = (x-xmin)/(xmax-xmin) 把所有的距离映射到0-1之间,适合于分布有明显的边界,比如说考试分数多是在0-100,无明显边界,比如说年薪有的人10000,有的人100000000,根本无法映射到一块,这时候我们需要均值方差归一化 Xscale = (x-xmean)/s 其中xmean是均值,s 为方差
from sklearn.preprocessing import StandardScaler standarscaler = StandardScaler() standarscaler.fit(X_train) X_train = standarscaler.transform(X_train) # 对矩阵进行归一化之后产生的结果,返回X_train X_test_standard = standarscaler.transform(X_test) # 对矩阵进行归一化之后产生的结果,返回X_testKNN算法到此结束了
