knn算法之超参数以及数据化归一(八)

一、超参数与调参

1.1、什么是超参数

1、超参数和模型参数
  • 超参数:算法运行前决定的参数
  • 模型参数:算法运行过程中学习的参数
  • knn算法knn算法没有模型参数,knn算法中的K就是典型的超参数
2、如何寻找到最好的超参数?
  • 领域知识:每一个领域都有适合该领域的超参数,如图像识别领域
  • 经验数值:很多机器学习库中的超参数会封装一些默认的数值,比如knn算法的k值默认为5
  • 实验搜索:对于具体的数据集,我们要根据数据集的具体情况得到最好的超参数就需要使用实验搜索
3、knn算法中的超参数
  • n_neighborsknn算法中的K值,默认为5

  • weights:用于标识每个样本的近邻样本的权重,可选择"uniform",“distance” 或自定义权重。默认"uniform",所有最近邻样本权重都一样。如果是"distance",则权重和距离成反比例;如果样本的分布是比较成簇的,即各类样本都在相对分开的簇中时,我们用默认的"uniform"就可以了,如果样本的分布比较乱,规律不好寻找,选择"distance"是一个比较好的选择;

  • algorithm:限定半径最近邻法使用的算法;可选‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’。
    brute:对应第一种线性扫描;
    kd_tree:对应第二种kd树实现;
    ball_tree:对应第三种的球树实现;
    auto:则会在上面三种算法中做权衡,选择一个拟合最好的最优算法。

  • leaf_size:这个值控制了使用kd树或者球树时, 停止建子树的叶子节点数量的阈值。这个值越小,则生成的kc树或者球树就越大,层数越深,建树时间越长,反之,则生成的kd树或者球树会小,层数较浅,建树时间较短。默认是30。这个值一般依赖于样本的数量,随着样本数量的增加,这个值必须要增加,否则不光建树预测的时间长,还容易过拟合。可以通过交叉验证来选择一个适中的值。当然,如果使用的算法是蛮力实现,则这个参数可以忽略;

  • metric,p:距离度量,默认闵可夫斯基距离 “minkowski”(p=1为曼哈顿距离, p=2为欧式距离);

  • metric_params:距离度量其他附属参数

  • n_jobs:并行处理任务数,主要用于多核CPU时的并行处理,加快建立KNN树和预测搜索的速度。n_jobs= -1,即所有的CPU核都参与计算

4、weights取值为distance时考虑距离
  • 如下图不考虑距离就是蓝方胜出
    在这里插入图片描述
5、曼哈顿距离、欧拉距离、闵可夫斯基距离区别

1.2、for循环实现网格搜索

1、寻找最好的K值
  • 代码
    import numpy as np
    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    from sklearn.neighbors import KNeighborsClassifier
    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,random_state = 666)
    best_k = 0
    best_score = 0.0
    for k in range(1,11):
        knnclassifier = KNeighborsClassifier(n_neighbors = k)
        knnclassifier.fit(X_train,y_train)
        score = knnclassifier.score(X_test,y_test)
        if score > best_score:
            best_score = score
            best_k = k
    print("best_k = " + str(best_k))
    print("best_score = " + str(best_score))
    
  • 输出结果
    在这里插入图片描述
2、寻找最好的weights值
  • 代码

    best_k = 0
    best_score = 0.0
    best_weights = ''
    for method in ["uniform","distance"]:
        for k in range(1,11):
            knnclassifier = KNeighborsClassifier(n_neighbors = k,weights = method)
            knnclassifier.fit(X_train,y_train)
            score = knnclassifier.score(X_test,y_test)
            if score > best_score:
                best_score = score
                best_k = k
                best_weights = method
    print("best_k = %s" %(best_k))
    print("best_score = %s"%(best_score))
    print("best_weights = %s"%(best_weights))
    
  • 输出结果
    在这里插入图片描述

3、寻找最高的p值
  • 代码:p=1为曼哈顿距离, p=2为欧式距离;默认是闵可夫斯基距离 “minkowski”;寻找最好的p值的前提是weights的值必须为distance

    best_k = 0
    best_score = 0.0
    best_p = 0
    for p in range(1,8):
        for k in range(1,11):
            knnclassifier = KNeighborsClassifier(n_neighbors = k,weights = "distance",p = p)
            knnclassifier.fit(X_train,y_train)
            score = knnclassifier.score(X_test,y_test)
            if score > best_score:
                best_score = score
                best_k = k
                best_p = p
    print("best_k = %s" %(best_k))
    print("best_score = %s"%(best_score))
    print("best_p = %s"%(best_p))
    
  • 测试结果
    在这里插入图片描述

1.3、grid search网格搜索

1、寻找最佳的超参数
  • 代码

    from sklearn.model_selection import GridSearchCV
    gird_params = [
        {"weights":["uniform"],
        "n_neighbors":[k for k in range(1,11)]},
        {"weights":["distance"],
        "n_neighbors":[k for k in range(1,11)],
        "p":[p for p in range(1,8)]}
    ] 
    knn_clf = KNeighborsClassifier()
    grid_search = GridSearchCV(knn_clf,gird_params)
    %%time 
    grid_search.fit(X_train,y_train)
    
  • 测试结果:用时将近四分钟
    在这里插入图片描述

2、Grid Search常用属性
  • best_estimator_:最好的classifier对象
  • best_params_:最好的超参数集合
  • best_score_:最好的测试准确率
  • 测试结果如下
    在这里插入图片描述
3、n_jobs超参数
  • 并行处理任务数,主要用于多核CPU时的并行处理,加快建立KNN树和预测搜索的速度。n_jobs= -1,即所有的CPU核都参与计算
  • 测试结果如下:比先前的四分钟要快了很多
    在这里插入图片描述
4、verbose超参数
  • 定义:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出。通俗来说就是对于预测最好超参数过程进行日志打印
  • 测试结果
    在这里插入图片描述

二、数据化归一

2.1、为什么要实现数据化归一

1、以下列这组数据为例
  • 如果使用欧拉距离进行计算,则样本间的举例被发现时间所主导,肿瘤大小的距离相对于发现时间来说完全可以忽略不计;这个时候就需要将数据进行归一化处理,否则算法得到的准确度就会有很大的误差。
    在这里插入图片描述
2、什么是数据归一化
  • 解决方案:将所有的数据映射到同一尺度;常用的有最值归一化和平均值方差归一化

2.2、最值归一化

1、最值归一化公式
  • 生成的数据都是0到1之间
    在这里插入图片描述
2、最值归一化存在的缺陷
  • 比较适用于分布有明显边界的情况,受outlier影响较大;举例说明:100个人,99个人月薪都是一万左右,而剩余一个人的月薪是一个亿,这个时候使用最值归一化就不能很好的反应这个数据的真实情况了;所以这个时候我们需要使用均值方差归一化
3、实现最值归一化
  • 代码

    import numpy as np
    X = np.random.randint(0,100,size = (10,10))
    X = np.array(X,dtype = float)
    for i in range(0,X.shape[1]):
        X[:,i] = (X[:,i] - np.min(X[:,i]))/(np.max(X[:,i]) - np.min(X[:,i]))
    X
    
  • 测试结果:得到的数值都是0到1之间
    在这里插入图片描述

2.3、均值方差归一化

1、什么是均值方差归一化
  • 定义:将所有的数据归一到均值为0方差为1的分布中;适用于数据分布没有明显的边界,有可能存在极端数据值的情况
  • 公式如下:样本值减去平均值然后除以方差
    在这里插入图片描述
2、实现均值方差归一化
  • 代码

    X2 = np.random.randint(0,100,size = (10,10))
    X2 = np.array(X2,dtype = float)
    for i in range(0,X2.shape[1]):
        X2[:,i] = (X2[:,i] - np.mean(X2[:,i]))/np.std(X2[:,i]) 
    X2
    
  • 测试结果
    在这里插入图片描述

3、验证上述数据的平均数是不是为0,方差是否为1

在这里插入图片描述

2.4、sklearn中的数据归一化:Scaler

1、注意事项
  • 测试数据集如何归一化?
    步骤一:计算出训练数据集的平均值和方差
    步骤二:测试数据集在训练数据集平均值和方差的基础上面进行归一化处理
    步骤三:以均值方差归一化为例,测试数据集归一化时需要减去训练数据集平均值然后除以训练数据集方差才能得到最终的归一化数据。在这里插入图片描述
  • 测试数据集这样归一化的原因:测试数据是模拟真实环境,真实环境可能无法得到所有测试数据点的均值和方差;对数据的归一化也是算法的一部分。
2、sklearn中归一化流程

在这里插入图片描述

3、使用sklearn中的StandardScaler进行训练数据集归一化
  • StandardScaler默认使用的是均值方差归一化

  • 训练数据集建模fit:

    import numpy as np
    from sklearn.preprocessing import StandardScaler
    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    iris = datasets.load_iris()
    X = iris.data
    Y = iris.target
    X_train,X_test,y_train,y_test = train_test_split(X,Y,train_size = 0.8,random_state = 555)
    standard = StandardScaler()
    standard.fit(X_train)
    '''
    获取训练数据集的平均值:即前面的mean_train
    '''
    standard.mean_
    '''
    获取训练数据集的方差:即前面的std_train
    '''
    standard.scale_
    '''
    获取训练数据集归一化后的数据集
    '''
    X_train_standard = standard.transform(X_train)
    
  • 测试结果
    在这里插入图片描述

4、使用sklearn中的StandardScaler进行测试据集归一化
  • 因为测试数据集归一化必须是在训练数据集的平均值和方差基础上,所以直接使用前面的standard对其进行均值方差归一化
    在这里插入图片描述
5、测试已归一化数据的准确率
  • 注意:测试准确率之前必须保证训练数据集与测试数据集都已经归一化

  • 代码

    from sklearn.neighbors import KNeighborsClassifier
    knn_classifier = KNeighborsClassifier(n_neighbors = 5)
    knn_classifier.fit(X_train_standard,y_train)
    knn_classifier.score(X_test_standard,y_test)
    
  • 测试结果
    在这里插入图片描述

2.5、实现自己的StandardScaler类

1、preprocessing.py模块
import numpy as np
'''
copy sklearn中的preprocessing
'''
class StandardScaler():
    def __init__(self):
        self.mean_ = None
        self.scale_ = None

    def fit(self,X):
        assert X.ndim == 2,"数据集必须是二维矩阵"
        self.mean_ = np.array([np.mean(X[:,i]) for i in range(0,X.shape[1])])
        self.scale_ = np.array([np.std(X[:, i]) for i in range(0, X.shape[1])])
        return self

    def transform(self,X):
        assert X.ndim == 2,"数据集必须是二维矩阵"
        assert self.mean_ is not None and self.scale_ is not None,"transform之前必须fit"
        assert X.shape[1] == len(self.mean_),'输入数据集列数必须合法'

        result_X = np.empty(shape=X.shape,dtype=float)
        for i in range(0,X.shape[1]):
            result_X[:,i] = (X[:,i] - self.mean_[i]) / self.scale_[i]
        return result_X
2、测试模块:standard_main.py
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

iris = datasets.load_iris()
X = iris.data
Y = iris.target
X_train,X_test,y_train,y_test = train_test_split(X,Y,train_size = 0.8,random_state = 555)
standard = StandardScaler()
standard.fit(X_train)

'''
获取训练数据集归一化后的数据集
'''
X_train_standard = standard.transform(X_train)
'''
获取测试数据集归一化后的数据集
'''
X_test_standard =  standard.transform(X_test)

'''
测试准确率
'''
knn_classifier = KNeighborsClassifier(n_neighbors = 4)
knn_classifier.fit(X_train_standard,y_train)
score = knn_classifier.score(X_test_standard,y_test)
print('准确率score = %s'%(score))


3、测试结果

在这里插入图片描述

4、sklearn中的最值归一化
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值