KNN-machine leanring notes
1.数据预处理
通常情况下我们的数据集都是按照一定规律导出,这时我们需要通过一定的方法都数据集进行打乱,这样才能更好的符合随机抽样的过程
# 方法1# 使用concatenate函数进行拼接,因为传入的矩阵必须具有相同的形状。
#因此需要对label进行reshape操作,reshape(-1,1)表示行数自动计算,1列。axis=1表示纵向拼接。
tempConcat = np.concatenate((X, y.reshape(-1,1)), axis=1)
# 拼接好后,直接进行乱序操作
np.random.shuffle(tempConcat)
# 再将shuffle后的数组使用split方法拆分
shuffle_X,shuffle_y = np.split(tempConcat, [4], axis=1)
# 设置划分的比例
test_ratio = 0.2test_size = int(len(X) * test_ratio)
X_train = shuffle_X[test_size:]
y_train = shuffle_y[test_size:]
X_test = shuffle_X[:test_size]
y_test = shuffle_y[:test_size
通过sklearn中的model_selection包我们可以直接对数据集进行拆封
from sklearn.model_selection import train_test_split
X_train,X_test, y_train, y_test =cross_validation.train_test_split(train_data,train_target,test_size=0.3, random_state=0)
train_data:被划分的样本特征集
train_target:被划分的样本标签
test_size:如果是浮点数,在0-1之间,表示样本占比;如果是整数的话就是样本的数量
random_state:是随机数的种子。
随机数种子:其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。比如你每次都填1,其他参数一样的情况下你得到的随机数组是一样的。但填0或不填,每次都会不一样。
随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则:
种子不同,产生不同的随机数;种子相同,即使实例不同也产生相同的随机数
2.分类精准度
accuracy_score:函数计算分类准确率,返回被正确分类的样本比例(default)或者是数量(normalize=False)
在多标签分类问题中,该函数返回子集的准确率,对于一个给定的多标签样本,如果预测得到的标签集合与该样本真正的标签集合严格吻合,则subset accuracy =1.0否则是0.0
因accuracy定义清洗、计算方法简单,因此经常被使用。但是它在某些情况下并不一定是评估模型的最佳工具。精度(查准率)和召回率(查全率)等指标对衡量机器学习的模型性能在某些场合下要比accuracy更好。
3.超参数
3.1 超参数简介
在KNN算法中我们默认传一个k值,但是这只是一个简单的KNN算法,在具体的实现过程中我们如何来体现模型的复杂性和精确性呢
这就涉及了机器学习领域中的一个重要问题:超参数。所谓超参数,就是在机器学习算法模型执行之前需要指定的参数。(调参调的就是超参数) 如kNN算法中的k。
与之相对的概念是模型参数,即算法过程中学习的属于这个模型的参数(kNN中没有模型参数,回归算法有很多模型参数)
如何选择最佳的超参数,这是机器学习中的一个永恒的问题。在实际业务场景中,调参的难度大很多,一般我们会业务领域知识、经验数值、实验搜索等方面获得最佳参数。
3.2超参数一-对于KNN来说寻找最好的K
# 指定最佳值的分数,初始化为0.0;设置最佳值k,初始值为-1
best_score = 0.0best_k = -1
for k in range(1, 11): # 暂且设定到1~11的范围内
knn_clf = KNeighborsClassifier(n_neighbors=k)
knn_clf.fit(X_train, y_train)
score = knn_clf.score(X_test, y_test) if score > best_score:
best_k = k
best_score = score
print("best_k = ", best_k)
print("best_score = ", best_score)
输出:best_k = 4best_score = 0.9916666666666667
3.3 超参数二-权重
回顾kNN算法思想时,我们应该还记得,对于简单的kNN算法,只需要考虑最近的n个数据是什么即可。但是如果我们考虑距离呢?
如果我们认为,距离样本数据点最近的节点,对其影响最大,那么我们使用距离的倒数作为权重。假设距离样本点最近的三个节点分别是红色、蓝色、蓝色,距离分别是1、4、3。那么普通的k近邻算法:蓝色获胜。考虑权重(距离的倒数):红色:1,蓝色:1/3 + 1/4 = 7/12,红色胜。
在 sklearn.neighbors 的构造函数 KNeighborsClassifier 中有一个参数:weights,默认是uniform即不考虑距离,也可以写distance来考虑距离权重(默认是欧拉距离,如果要是曼哈顿距离,则可以写参数p(明可夫斯基距离的参数),这个也是超参数)
因为有两个超参数,因此使用双重循环,去查找最合适的两个参数,并打印。
# 两种方式进行比较
best_method = ""best_score = 0.0
best_k = -1for method in ["uniform","distance"]:
for k in range(1, 11):
knn_clf = KNeighborsClassifier(n_neighbors=k, weights=method, p=2)
knn_clf.fit(X_train, y_train)
score = knn_clf.score(X_test, y_test) if score > best_score:
best_k = k
best_score = score
best_method = method
print("best_method = ", method)
print("best_k = ", best_k)
print("best_score = ", best_score)
输出:best_method = distance
best_k = 4best_score = 0.9916666666666667
3.4超参数网格搜索
通过sklearn中封装的超参数网格搜索方法Grid Search
在进行网格搜索之前,首先需要定义一个搜索的参数param_search。是一个数组,数组中的每个元素是个字典,字典中的是对应的一组网格搜索,每一组网格搜索是这一组网格搜索每个参数的取值范围。键是参数的名称,值是键所对应的参数的列表。
param_search = [
{ "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)]
}
]
knn_clf = KNeighborsClassifier()# 调用网格搜索方法
from sklearn.model_selection import GridSearchCV
# 定义网格搜索的对象grid_search,其构造函数的第一个参数表示对哪一个分类器进行算法搜索
#,第二个参数表示网格搜索相应的参数
grid_search = GridSearchCV(knn_clf, param_search)
面就是针对X_train, y_train,使用grid_search在param_search列表中寻找最佳超参数组:
%%time
grid_search.fit(X_train, y_train)
Wall time: 2min 23s
GridSearchCV(cv=None, error_score='raise',
estimator=KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=1, n_neighbors=5, p=2,
weights='uniform'),
fit_params=None, iid=True, n_jobs=1,
param_grid=[{'weights': ['uniform'], 'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}, {'weights': ['distance'], 'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'p': [1, 2, 3, 4, 5]}],
pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
scoring=None, verbose=0)
可以使用网格搜索的评估函数来返回最佳分类起所对应的参数,也可以查看最佳参数的分类器的准确度。
我们会注意到,best_estimator_
和best_score_
参数后面有一个_。这是一种常见的语法规范,不是用户传入的参数,而是根据用户传入的规则,自己计算出来的结果,参数名字后面接_
grid_search.best_estimator_
输出:KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=1, n_neighbors=3, p=3,
weights='distance')
总结
在这篇文章中,我们借助kNN分类算法,学习了如下知识点:
-
为了验证模型的好坏,将数据集划分为训练数据集和测试数据集,这样我们就可以对测试数据集的进行预测,然后使用label进行验证。
-
在我们得到了分类结果之后,就可以使用分类正确的数据点比上总的测试数据点,这样就可以计算出accuracy分类精准度。
-
最后我们以kNN算法为例,探究了不同的超参数对模型的影响,使用sklearn中封装好的网格搜索算法,可以帮助我们进行基础调参。