kNN学习笔记
一、kNN基础
二、什么是机器学习
三、超参数
四、数据归一化
五、总结
一、kNN基础
实现简单
使用的数学知识少
适合入门
- 简单的来讲,KNN算法就是找出x最近邻的k个样本,k个样本中,找出与之特征相似样本的数量最多的类别,然后将x分入该类别。
- 以上图为例,设k = 3,即找出与蓝色的点最详尽的三个点,很显然,最近的三个点都为红色的点,那么该蓝色的点就位红色这一类。相应的,如果蓝色点的最近的三个点中有两个点为红色,一个为蓝色,则仍然归类为红色一类,反之亦然。
二、什么是机器学习
- 输入训练数据集,在机器学习算法训练生成模型,输入样例到模型之后得到预测的输出结果
* - knn是一个不需要训练过程的算法
- knn是特殊的,是没有模型的算法
- 为了和其它算法统一,可以说训练集本身就是模型
- 训练数据集、测试数据集
-
训练得到的模型能够直接在真实环境中使用
- 问题:
-
模型如果很差会造成真实损失
-
真实环境中不能拿到真实的label(target)
- 因此需要训练数据集合测试数据集分离:
-
使用封装好的train_test_split,或者十折交叉验证(10-fold cross validation)
# 一个demo
# 导入封装好了knn算法
from sklearn.neighbors import KNeighborsClassifier
from sklearn import datasets
from sklearn.model_selection import train_test_split
knn_clf = KNeighborsClassifier(n_neighbors = 3) #这里的n_neighbors = 3即前面讲到的k = 3
iris = datasets.load_iris() #获取鸢尾花的数据
#用X、y来接受鸢尾花的特征值和类别
X = iris.data
y = iris.target
#将数据分为训练集和测试集
X_train, x_test, y_train, y_test = train_test,split(X, y, test_size = 0.2)
#做模型训练
knn_clf.fit(X_train, y_train)
#数据预测
y_predict = knn_clf.predict(X_test)
#满足预测结果与实际结果相同的率,即预测成功率
rate = sum(y_predict == y_test)/y_test
#同上一列所达到的目的一样
knn_clf.score(X_test, y_test)
#也可以使用accuracy_score来评价预测成功率
from sklearn.metrics import accuracy_score
accuracy_score(y_predict, y_test)
三、超参数
在机器学习的上下文中,超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果。
-
简单的来说,超参数就是为了来提高学习的性能和效果。
-
超参数:在算法运行前需要决定的参数
-
模型参数:算法过程中学习的参数
寻找好的参数:
领域知识
经验数值
- 这就涉及了一些问题,怎么找到最好的超参数呢?以寻找最好的k为例:
# 可以写在上一个代码示例后面
best_score = 0.0
best_k = -1
# 在1-11之间寻找最好的k
for k in range(1, 11):
knn = KNeighborsClassifier(n_neighbors = k)
knn.fit(X_train, y_train)
score = knn.score(X_test, y_test)
if score > best_score:
best_score = score
best_k = k
print("best_k = ", best_k)
print("best_k = ", best_score)
-
上例只考虑了k的最好值,还有其它的超参数类型:例如:下图中的sample最近邻的三个点都有相应的weight,三个点中,有两个为蓝色一类的,一个绿色,但是绿色的权重100 > 50+40,所以算上权重的话,sample应该归为绿色一类。代码可以试着自己写一下。
-
曼哈顿距离:每个维度上的差值的绝对值之和
欧拉距离:每个维度上的差值的平方之和的平方根
闵可夫斯基距离: 每个维度上的距离绝对值的p次方之和的p次方根
- 你可以思考一下闵可夫斯基距离中的p可否作为一个超参数
- 事实上,在寻找各超参数或者模型参数的过程中,不需要自己不断地遍历。可以使用网格搜索(Grid Search)
param_grid = [
{
'weights':['uniform'],
'n_neighbors':[i for i in range(1,11)]
},
{
'weights':['distance'],
'n_neighbors': [i for i in range(1,11)],
'p': [i for i in range(1,6)]
}
]
from sklearn.model_selection import GridSearchCV
grid_search = GridSearchCV(knn, param_grid)
gsCV = grid_search.fit(X_train , y_train)
print(gsCV)
#
四、数据归一化
为什么要进行数据归一化呢?以下图所示:(该图的数据为我现场写的,仅作为解释,可能会有误解)对如下数据做处理,X2的参数中数据明显偏大,分类过程受到X2的影响明显会更大,但是其中一项数据对结果的影响更大,肯定会影响到最终预测的准确率,所以做标准归一化操作很重要,要避免某一项或某几项会明显影响结果的情况。
X1 | X2 | y |
---|---|---|
7 | 100 | 1 |
9 | 76 | 0 |
8 | 83 | 1 |
- 这里给出以下两种方式:
-
最值归一化: 把所有的数据映射到0-1之间
使用于分布有明显边界的情况;受到outlier影响较大
缺点:不能解决数据偏值很大的数据
例如:大部分的数据的值都在100以内,有小部分的重要数据在500以上,最值归一化就难以处理,即若在预测时需要预测500以上的数据,那么由于数据量少,预测结果就不准确 -
均值方差归一化:将所有数据归一到均值为0方差为1的分布中
数据分布没有明显的边界;有可能存在极端数据值真实环境很有可能无法得到所有测试数据的均值和方差
对数据的归一化也是算法的一部分,所以测试数据进行归一化时,需要用到测试数据的均值和方差,(X_test - mean_train)/std_train, 要保存测试数据值的均值和方差,给测试训练集使用
- 于是引入scikit-learn中的standardScaler方法:
from sklearn.preprocessing import StandardScaler
stand = StandardScaler()
stand.fit(X_train)
#打印出均值和方差
print(stand.mean_)
print(stand.scale_)
#将X_train转化为均值为0,方差为1的形式
X_train = stand.transform(X_train)
print(X_trian)
X_test_t = stand.transform(X_test)
#对现在的数据进行训练并看最终的预测成功率
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, y_train)
knn.score(X_test, y_test)
五、总结
- knn 可以解决分类问题,天然地可以解决多分类问题且思想简单
- knn也可以解决回归问题:可以了解KNeighborsRegressor方法
- 缺点:
- 最大缺点:效率低下。如果训练集有m个样本,n个特征,则预测一个新的数据,需要O(m*n)。优化:使用KD-Tree,Ball-Tree
- 高度数据相关
- 预测结果具有不可解释性
* (维数灾难)随着维度的增加,看似很近的两个点之间的距离越来越大
* 解决方法:降维 PCA方法