K近邻算法--KNN(k-nearest neighbors)、K折交叉验证、特征缩放

什么是KNN?

  • KNN 算法通常应用于分类算法,对于要进行预测的样本,它的预测规则是:计算各个训练样本与要进行预测的样本之间的距离(常用欧式距离来表示),然后根据指定的k值统计距离预测样本最近的前k个样本中属于各个类别的样本数量,预测结果就是类别中样本数量最多的那一个。

K值的奇偶性

  • k值通常选奇数,这样就可以避免出现平局的情况。假设只有两个类别c1, c2,k=4,如果对于某一个测试数据,与它最近的前四个样本中,属于c1的有两个,属于c2的有两个,这是程序将无法对测试数据的类别进行判断。

sklearn实现KNN

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import numpy as np

# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 切分样本
# random_state就像是随机种子,使得我们每次分隔的训练样本集和测试样本集没有变化
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2003)

clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(X_train, y_train)

# count_nonzero用来统计数组中非零元素的个数
correct = np.count_nonzero((clf.predict(X_test) == y_test) == True)
print("Accuracy is: %.3f" % (correct / len(X_test)))

自实现KNN

from sklearn import datasets
from collections import Counter
from sklearn.model_selection import train_test_split
import numpy as np

# 加载iris数据集,并进行切分
iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2003)

def euc_dis(instance1, instance2):
    """
    计算两个样本之间的欧式距离
    """
    dist = np.sqrt(np.sum((instance1 - instance2) ** 2))
    return dist

def knn_classify(X, y, test_Instance, k):
    """
    给定测试数据test_Instance,通过knn算法预测它的标签
    X:训练样本的特征
    y:训练样本的标签
    """
    # 首先计算测试数据同训练数据中每个样本之间的距离
    distances = [euc_dis(x, test_Instance) for x in X]
    # 获取与测试数据最近的前k的数据的下标
    # argsort函数返回数组从小到大排列的索引值(下标)
    kneighbors = np.argsort(distances)[:k]
    # 统计距离最近的前k的数据属于各个种类的数量
    # Counter返回的是一个字典
    count = Counter(y[kneighbors])
    # 从字典中取出出现次数最多的那个元素
    # most_common函数返回的是一个列表,对于列表中的每个元素,
    # 元素的第一个是元素值,第二位是元素出现的次数,它默认返回所有元素,也可以指定个数
    return count.most_common()[0][0]

K值的选择–K折交叉验证(K-Fold Cross Validation)

  • K折交叉验证,会在我们已经划分好的训练集和测试集中的训练集进行再次划分,把它划分为训练集和验证集;使用规则:对于不同的k值,我们先使用训练集训练模型,然后再使用验证集评估模型的准确率,这样对于每一个k值我们会得到一个相应的准确率,则准确率较高的k即为我们要使用的k。
  • 测试集作用:用来测试模型是否满足上线要求,它不能用于模型训练过程的任何一个环节。

sklearn实现K折交叉验证实现

import numpy as np 
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import KFold

# 导入数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 定义k的候选集
ks = [1, 3, 5, 7, 9, 11, 13, 15]

"""
KFold返回的是每一折中训练数据和验证数据的下标
假设样本为:[1, 3, 5, 6, 11, 12, 43, 12, 44, 2]
则可能的kf格式为(前面是训练数据的下标,后面是验证集的下标):
[0, 1, 2, 3, 4, 5, 6, 7, 8] [9, 10]
"""

# 5折交叉验证
kf = KFold(n_splits=5, random_state=2001, shuffle=True)
# 用来保存最好的k值以及所对应的k的准确率
best_k = ks[0]
best_score = 0

# 依次对候选集中的每个k值进行交叉验证
for k in ks:
    cur_score = 0
    # 使用每一折进行训练并记录它的分数
    for train_index, valid_index in kf.split(X):
        # 初始化一个分类器
        clf = KNeighborsClassifier(n_neighbors=k)
        # 训练
        clf.fit(X[train_index], y[train_index])
        # 对得分进行累加
        cur_score += clf.score(X[valid_index], y[valid_index])
    # 求当前k的平均分
    avg_score = cur_score / 5
    if avg_score > best_score:
        best_score = avg_score
        best_k = k
    print("current best score is %.2f" % best_score, "best k: %d" % best_k)
print("after cross validation, the final best k is: %d" % best_k)

网格搜索K折交叉验证实现

from sklearn.model_selection import GridSearchCV  # 网格搜索
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier

iris = datasets.load_iris()
X = iris.data
y = iris.target

# 设置需要搜索的k值,'n_neighbors'是knn的参数
parameters = {"n_neighbors": [1, 3, 5, 7, 9, 11, 13, 15]}
# 对于要进行选择的参数,不需要填入
knn = KNeighborsClassifier()

# 分类器,需要优化的参数(字典或列表形式),几折交叉验证
clf = GridSearchCV(knn, parameters, cv=5)
clf.fit(X, y)

print(clf.best_score_, clf.best_params_)

特征缩放

  • 线性归一化Min-max Normalization
    x_new = (x - min(x)) / (max(x) - min(x))
  • 标准差归一化Z-score Normalization
    x_new = (x - mean(x)) / std(x)
  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值