K近邻算法
这里面涉及到一些算法实现的包,比如得到的每个点,求距离后怎么处理的问题。
# 前面求欧氏距离就不赘述了,这里主要是补充一点求出结果后怎么处理的问题
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_test
KNN算法到此结束了