请选择 进入手机版 | 继续访问电脑版
查看: 88|回复: 0

python 留一交叉验证的实例

[复制链接]

2198

主题

0

回帖

7027

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
7027
发表于 2022-10-9 02:53:46 来自手机 | 显示全部楼层 |阅读模式
python 留一交叉验证


基本原理

K折交叉验证
简单来说,K折交叉验证就是:


  • 把数据集划分成K份,取出其中一份作为测试集,另外的K - 1份作为训练集。
  • 通过训练集得到回归方程,再把测试集带入该回归方程,得到预测值。
  • 计算预测值与真实值的差值的平方,得到平方损失函数(或其他的损失函数)。
  • 重复以上过程,总共得到K个回归方程和K个损失函数,其中损失函数最小的回归方程就是最优解。
留一交叉验证
留一交叉验证是K折交叉验证的特殊情况,即:将数据集划分成N份,N为数据集总数。就是只留一个数据作为测试集,该特殊情况称为“留一交叉验证”。

代码实现

  1. '''留一交叉验证'''
  2. import numpy as np

  3. # K折交叉验证
  4. data = [[12, 1896], [11, 1900], [11, 1904], [10.8, 1908], [10.8, 1912], [10.8, 1920], [10.6, 1924], [10.8, 1928],
  5.         [10.3, 1932], [10.3, 1936], [10.3, 1948], [10.4, 1952], [10.5, 1956], [10.2, 1960], [10.0, 1964], [9.95, 1968],
  6.         [10.14, 1972], [10.06, 1976], [10.25, 1980], [9.99, 1984], [9.92, 1988], [9.96, 1992], [9.84, 1996],
  7.         [9.87, 2000], [9.85, 2004], [9.69, 2008]]

  8. length = len(data)

  9. # 得到训练集和测试集
  10. def Get_test_train(length, data, i):
  11.     test_data = data[i]  # 测试集
  12.     train_data = data[:]
  13.     train_data.pop(i)  # 训练集
  14.     return train_data, test_data

  15. # 得到线性回归直线
  16. def Get_line(train_data):
  17.     time = []
  18.     year = []
  19.     average_year_time = 0
  20.     average_year_year = 0

  21.     for i in train_data:
  22.         time.append(i[0])
  23.         year.append(i[1])

  24.     time = np.array(time)
  25.     year = np.array(year)

  26.     average_year = sum(year) / length  # year拔
  27.     average_time = sum(time) / length  # time拔

  28.     for i in train_data:
  29.         average_year_time = average_year_time + i[0] * i[1]
  30.         average_year_year = average_year_year + i[1] ** 2
  31.     average_year_time = average_year_time / length  # (year, time)拔
  32.     average_year_year = average_year_year / length  # (year, year)拔
  33.     # 线性回归:t = w0 + w1 * x
  34.     w1 = (average_year_time - average_year * average_time) / (average_year_year - average_year * average_year)
  35.     w0 = average_time - w1 * average_year
  36.     return w0, w1

  37. # 得到损失函数
  38. def Get_loss_func(w0, w1, test_data):
  39.     time_real = test_data[0]
  40.     time_predict = eval('{} + {} * {}'.format(w0, w1, test_data[1]))
  41.     loss = (time_predict - time_real) ** 2
  42.     dic['t = {} + {}x'.format(w0, w1)] = loss
  43.     return dic

  44. if __name__ == '__main__':
  45.     dic = {}  # 存放建为回归直线,值为损失函数的字典

  46.     for i in range(length):
  47.         train_data, test_data = Get_test_train(length, data, i)
  48.         w0, w1 = Get_line(train_data)
  49.         Get_loss_func(w0, w1, test_data)
  50.         dic = Get_loss_func(w0, w1, test_data)

  51.     min_loss = min(dic.values())
  52.     best_line = [k for k, v in dic.items() if v == min_loss][0]
  53.     print('最佳回归直线:', best_line)
  54.     print('最小损失函数:', min_loss)
复制代码

留一法交叉验证 Leave-One-Out Cross Validation

交叉验证法,就是把一个大的数据集分为 k 个小数据集,其中 k−1 个作为训练集,剩下的 1 11 个作为测试集,在训练和测试的时候依次选择训练集和它对应的测试集。这种方法也被叫做 k 折交叉验证法(k-fold cross validation)。最终的结果是这 k 次验证的均值。
此外,还有一种交叉验证方法就是 留一法(Leave-One-Out,简称LOO),顾名思义,就是使 k kk 等于数据集中数据的个数,每次只使用一个作为测试集,剩下的全部作为训练集,这种方法得出的结果与训练整个测试集的期望值最为接近,但是资本过于庞大。

我们用SKlearn库来实现一下LOO

  1. from sklearn.model_selection import LeaveOneOut

  2. # 一维示例数据
  3. data_dim1 = [1, 2, 3, 4, 5]

  4. # 二维示例数据
  5. data_dim2 = [[1, 1, 1, 1],
  6.              [2, 2, 2, 2],
  7.              [3, 3, 3, 3],
  8.              [4, 4, 4, 4],
  9.              [5, 5, 5, 5]]

  10. loo = LeaveOneOut() # 实例化LOO对象

  11. # 取LOO训练、测试集数据索引
  12. for train_idx, test_idx in loo.split(data_dim1):
  13.     # train_idx 是指训练数据在总数据集上的索引位置
  14.     # test_idx 是指测试数据在总数据集上的索引位置
  15.     print("train_index: %s, test_index %s" % (train_idx, test_idx))

  16. # 取LOO训练、测试集数据值
  17. for train_idx, test_idx in loo.split(data_dim1):
  18.     # train_idx 是指训练数据在总数据集上的索引位置
  19.     # test_idx 是指测试数据在总数据集上的索引位置
  20.     train_data = [data_dim1[i] for i in train_idx]
  21.     test_data = [data_dim1[i] for i in test_idx]
  22.     print("train_data: %s, test_data %s" % (train_data, test_data))
复制代码
data_dim1的输出:
  1. train_index: [1 2 3 4], test_index [0]train_index: [0 2 3 4], test_index [1]train_index: [0 1 3 4], test_index [2]train_index: [0 1 2 4], test_index [3]train_index: [0 1 2 3], test_index [4]
  2. train_data: [2, 3, 4, 5], test_data [1]train_data: [1, 3, 4, 5], test_data [2]train_data: [1, 2, 4, 5], test_data [3]train_data: [1, 2, 3, 5], test_data [4]train_data: [1, 2, 3, 4], test_data [5]
复制代码
data_dim2的输出:
  1. train_index: [1 2 3 4], test_index [0]train_index: [0 2 3 4], test_index [1]train_index: [0 1 3 4], test_index [2]train_index: [0 1 2 4], test_index [3]train_index: [0 1 2 3], test_index [4]
  2. train_data: [[2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5]], test_data [[1, 1, 1, 1]]train_data: [[1, 1, 1, 1], [3, 3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5]], test_data [[2, 2, 2, 2]]train_data: [[1, 1, 1, 1], [2, 2, 2, 2], [4, 4, 4, 4], [5, 5, 5, 5]], test_data [[3, 3, 3, 3]]train_data: [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [5, 5, 5, 5]], test_data [[4, 4, 4, 4]]train_data: [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]], test_data [[5, 5, 5, 5]]
复制代码
以上为个人经验,希望能给大家一个参考,也希望大家多多支持趣UU。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
打赏作者
  • 0
  • 0
  • 0
  • 0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表