zoukankan      html  css  js  c++  java
  • 交叉验证初识

    交叉验证

    这只是做一个简单的笔记, 毕竟作为调参侠, 很多需要人工设置的超参数, 是优化模型里非常重要一部分, 凡是涉及到了设置超参数, 必然要做交叉验证 or 网格搜索 呀, 选择更好的模型嘛.

    不使用交叉验证

    比如像 线性回归, 就可以不用交叉验证. 但有一点是基本的, 样本的划分

    • 训练集
    • 测试集

    这是最为基本的尝试, 用训练集来训练模型参数, 用测试集来验证模型的预测效果, 比例上,我一般初次设定, 75%的样本做训练, 25%做预测. 当然, 这也看样本的质量如何, 当然也会考虑到一些训练上的问题, 比如:

    • 欠拟合 vs 过拟合
    • 样本不均衡

    感觉这两个问题都属于经验问题了, 具体问题具体分析. 尤其是样本不均衡问题, 嗯, 我以前做市场数据分析的时候, 就会采取重采样,或者假定是满足某个分布, 然后随机生成一些数据, 或者, 随机复制一些原来的数据, 当然, 方法很多, 这要看具体的需求是怎样的, 还是就是一个经验性问题吧.

    交叉验证

    举个5折交叉验证的例子就好了.

    假设我现在有 120条数据(样本), 分别给编号为 1~120.

    首先-划分训练集和测试集

    这里, 我以 101~120 号样本作为 测试集, 编号为 1~100 作为训练集

    然后-对训练集再分为 n 等份

    这里取5折, 也就是将 训练集 1-100 号的样本, 分为5份, 也就是每份 20条样本. 记这5份样本集, 分别为 A,B,C,D,E, 每次从中取一个集作为测试集, 其余4份作为训练集, 这样分别训练 5个模型.

    • train(B,C,D,E) -> model_1 -> test(A) -> score1

    • train(A,C,D,E) -> model_2 -> test(B) -> score2

    • train(A,B,D,E) -> model_3 -> test(C) -> score3

    • train(A,B,C,E) -> model_4 -> test(D) -> score4

    • train(A,B,C,D) -> model_4 -> test(E) -> score5

    (score =frac {1}{5}sum limits _{i=1}^5 score i)

    这个score 呢, 就可以大致 得到, 一会儿呀那 编号为 101~120 的测试数据, 的效果有多好.

    对于分类问题, 可用使用分层抽样 来生成数据, 保证正负例的比例在训练和测试集中的比例相同, 小结几个明显的优势

    • 交叉验证可以帮助调参, 得到最优模型参数
    • 可以进行模型选择
    • 可以进行特征选择, 对比不同特征组合,优化模型

    SKlearn 的交叉验证调参

    以SVC为例, 对 C (松弛) 进行调参

    # 调参侠
    parameter_candidates = [
        {'C':[1,10,100,1000], 'kernel':['linear']},
        {'C':[1,10,100,1000], 'gamma':[0.001,0.0001],'kernel':['rbf']}
    ]
    
    clf = GridSearchCV(estimator=svm.SVC,
                      param_grid=parameter_candidates,
                      cv=5, n_jobs=-1)
    
    clf.fit(X_Train, y_Train)
    
    # 查看训练的结果
    print('best score:', clf.best_score)
    print('C:', clf.best_estimator_.C)
    print('best kernel:', clf.best_estimator_.kernel)
    print('best Gamma:', clf.best_estimator_.gamma)
    
    

    VC 维

    之前在svm的时候用了kernel, 即在低维空间下完成了高维空间的运算, 确实有些美滋滋. 不禁会想起一个问题, 为什么kernel, (增加样本的维度)就可以将问题变得容易, 这里背后有一个理论支撑, 即VC维理论.

    一个假设空间H的 VC dimension, 是这个空间 H 最多能够 shatter 掉点的数量, 记为dvc(H)

    • 假设空间可以看做模型的复杂度
    • shatter , 打散, 指不论数据的分布如何, H 都要把它区分开
    • shatter 点的数量, 指 H 最多能区分多少个数据. 越复杂的 H, 能够区分的点数就越多, VC维度也就越大
    • 只要有一组数据点(n个) 能被 shatter, 就认为VC维度为n, 不要求所有的个数为n的数据点都能被shatter.

    为什么要有VC维这个东西能? 我们知道, 机器学习从本质来看, 是对真实模型的近似于逼近 真实模型与近似模型之间的误差的累计, 就叫做风险.

    真实的误差,其实未知的, 处理方式,就是通过人工打标签 的方式, 对样本进行模型训练, 预测值 - 人工标记值 = 经验风险.

    包括我在学生时期,做统计模型的时候, 也总是希望能尽可能地去拟合属于, 为了更好地拟合样本, 于是把模型弄得非常复杂( VC 维很高 ), 然后就导致了过拟合问题. 在统计学中引入了一个 泛化误差界 的概念. 这样一来,

    真实风险 = 经验风险 + 置信风险

    置信风险, 置信区间, 这个我熟呀, 统计学还是掌握挺好的. 置信风险和分类函数的VC维有关. **样本越大, 置信风险越小; VC维越大, 表示模型越复杂, 推广能力越差, 结构风险越大.

    case: 线性分类器 VC = 3

    对于3个数据点, 共有 2**3 = 8 种赋值类别标签的方式. 而线性分类器,总能把其正确分为 两类, 但4个就不行了.

    就画一条线, 对于3个点, 总能将其分开.

    这方面,我也不怎么会用到, 对会用的神经网络, 暂时没啥兴趣. 先这样吧, 了解一下算了.

  • 相关阅读:
    python模块总结(一)命令行解析模块argparse
    TCP(一)三次握手和四次挥手
    容器网络(四)vxlan
    容器网络(三)容器间通信
    kvm虚拟化(二)网络虚拟化
    KVM虚拟化(一)创建虚拟机
    数字操作 —— 9_ 回文数
    数字操作 —— 8_字符串转换整数(atoi)
    数字操作 —— 7_整数反转
    字符串操作 —— 763_划分字母区间
  • 原文地址:https://www.cnblogs.com/chenjieyouge/p/11959687.html
Copyright © 2011-2022 走看看