大师兄的Python机器学习笔记:数据预处理
大师兄的Python机器学习笔记:实现评估模型
一、重抽样方法
1. 关于重抽样方法(Resampling Methods)
重抽样是统计学的重要工具,主要为了实现以下目标:
- 估计样本统计量(如中位数、方差、分位数等)的精度;
- 在做显著性检验(significance tests)时交换数据点的标签;
- 用随机的样本子集验证模型的有效性。
2. 重抽样方法的种类
重抽样的方法包括:
- 自助法(Booststraping)
- 刀切法(Jackknife)
- 置换验证(permutation tests)
- 交叉验证(Cross-validation)
... ...
3. 关于交叉验证(Cross-Validation)
- 交叉验证是一种模型验证技术,它主要用于估计一个预测模型的准确性。
- 首先将样本分割成训练集和检验集两部分。
- 其中训练集用来训练预测模型,检验集用来检验模型的准确性。
- 在训练集上建模,在检验集评价分析模型。
- 为了降低变异度,需要做多轮交叉验证,平均评价指标。
二、交叉验证的实现
1. 简单验证法(train_test_split)
- 随机将样本数据分为两份,用训练集来训练模型,在测试集上验证模型及参数。
- 优点:简单,只需要将数据分成两份。
- 缺点:只进行了一次划分,数据结果偶然性大。
- 实现方法一:自己写算法
>>>import os
>>>import pandas as pd
>>>from random import randrange,seed
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>>def train_test_split(dataset,train=0.6):
>>> # train_test_split
>>> seed(100)
>>> train_basket = []
>>> train_size = train*len(dataset)
>>> dataset_copy = list(dataset)
>>> while len(train_basket)<train_size:
>>> random_choose_some_element = randrange(len(dataset_copy))
>>> train_basket.append((dataset_copy.pop(random_choose_some_element)))
>>> return train_basket,dataset_copy
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> train_basket,test_basket = train_test_split(data_cases)
>>> print(f'共有数据:{len(data_cases)}个\n其中训练数据:{len(train_basket)}个\n测试数据:{len(test_basket)}')
共有数据:56541个
其中训练数据:33925个
测试数据:22616个
- 实现方法二:用
sklearn
包中的算法
>>> import os
>>> import pandas as pd
>>> from sklearn.model_selection import train_test_split
>>> def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>> def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>> if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> train_basket,test_basket = rain_test_split(data_cases,test_size=0.4,random_state=100,shuffle=True)
>>> print(f'共有数据:{len(data_cases)}个\n其中训练数据:{len(train_basket)}个\n测试数据:len(test_basket)}')
共有数据:56541个
其中训练数据:33924个
测试数据:22617个
2. K折交叉验证(K-Folder Cross Validation)
- K折交叉验证会把样本数据随机的分成K份,每次随机的选择K-1份作为训练集,剩下的1份做测试集。
-
相当于做了K次简单验证法。
- 优点:降低由一次随机划分带来的偶然性,提高其泛化能力,提高对数据的使用效率。
- 缺点:可能存在一种情况:数据集有5类,抽取出来的也正好是按照类别划分的5类, 造成数据高偏差。
- 实现方法一:自己写算法
>>>import os
>>>import pandas as pd
>>>from random import randrange,seed
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>>def k_fold_cross_validation_split(dataset,folds=10):
>>> seed(100)
>>> basket_for_splitted_data = []
>>> fold_size = int(len(dataset)/folds)
>>> dataset_copy = list(dataset)
>>> for i in range(folds):
>>> basket_for_random_choosen_fold = []
>>> while len(basket_for_random_choosen_fold) < fold_size:
>>> random_choose_some_element = randrange(len(dataset_copy))
>>>>basket_for_random_choosen_fold.append(dataset_copy.pop(random_choose_some_element))
>>> basket_for_splitted_data.append(basket_for_random_choosen_fold)
>>> return basket_for_splitted_data
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> basket_for_splitted_data = k_fold_cross_validation_split(data_cases)
>>> for i in range(len(basket_for_splitted_data)):
>>> print(f"分组{i+1}共有数据:{len(basket_for_splitted_data[i])}")
分组1共有数据:5654
分组2共有数据:5654
分组3共有数据:5654
分组4共有数据:5654
分组5共有数据:5654
分组6共有数据:5654
分组7共有数据:5654
分组8共有数据:5654
分组9共有数据:5654
分组10共有数据:5654
- 实现方法二:用
sklearn
包中的算法
>>>import os
>>>import pandas as pd
>>>from random import randrange,seed
>>>from sklearn.model_selection import KFold
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> kf = KFold(n_splits=10)
>>> basket_for_splitted_data = kf.split((data_cases))
>>> i = 0
>>> while True:
>>> i+=1
>>> try:
>>> print(f'第{i}组数据:{next(basket_for_splitted_data)}')
>>> except StopIteration as e:
>>> break
第1组数据:(array([ 5655, 5656, 5657, ..., 56538, 56539, 56540]), array([ 0, 1, 2, ..., 5652, 5653, 654]))
第2组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([ 5655, 5656, 5657, ..., 11306, 11307, 1308]))
第3组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([11309, 11310, 11311, ..., 16960, 16961, 6962]))
第4组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([16963, 16964, 16965, ..., 22614, 2615, 2616]))
第5组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([22617, 22618, 22619, ..., 28268, 8269, 8270]))
第6组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([28271, 28272, 28273, ..., 33922, 3923, 3924]))
第7组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([33925, 33926, 33927, ..., 39576, 9577, 9578]))
第8组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([39579, 39580, 39581, ..., 45230, 5231, 5232]))
第9组数据:(array([ 0, 1, 2, ..., 56538, 56539, 56540]), array([45233, 45234, 45235, ..., 50884, 0885, 0886]))
第10组数据:(array([ 0, 1, 2, ..., 50884, 50885, 50886]), array([50887, 50888, 50889, ..., 56538, 6539, 56540]))
3. 留一交叉验证(Leave-one-out Cross Validation)
- 与K折交叉验证法类似,但是每次只留下一个样本做测试集,其它样本做训练集,如果有k个样本,则需要训k次,测试k次。
-
相当于做了k*n次简单验证法。
- 优点:样本利用率最高。
- 缺点:速度慢,消耗资源。
- 实现方法一:自己写算法
>>>import os
>>>import pandas as pd
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>>def leave_one_out_Cross_Validation(dataset):
>>> basket_for_splitted_data = []
>>> fold_size = int(len(dataset))
>>> dataset_copy = list(dataset)
>>> for i in range(fold_size):
>>> train = dataset_copy.copy()
>>> test = dataset_copy[i]
>>> del train[i]
>>> basket_for_splitted_data.append((test,train))
>>> return basket_for_splitted_data
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> basket_for_splitted_data = leave_one_out_Cross_Validation(data_cases)
>>> print(f'数据共有{len(basket_for_splitted_data)}列')
数据共有56541列
- 实现方法二:用
sklearn
包中的算法
>>> import os
>>> import pandas as pd
>>> from sklearn.model_selection import LeaveOneOut
>>> def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>> def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>> if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> loo = LeaveOneOut()
>>> basket_for_splitted_data = loo.split(data_cases)
>>> i = 0
>>> while True:
>>> i += 1
>>> try:
>>> print(f'第{i}组数据:{next(basket_for_splitted_data)}')
>>> except StopIteration as e:
>>> break
... ...
第56539组数据:(array([ 0, 1, 2, ..., 56537, 56539, 56540]), array([56538]))
第56540组数据:(array([ 0, 1, 2, ..., 56537, 56538, 56540]), array([56539]))
第56541组数据:(array([ 0, 1, 2, ..., 56537, 56538, 56539]), array([56540]))
4 自助法(Bootstrapping)
- 自助法可以理解为有放回采样或重复采样的交叉验证。
- 比如我们有m个样本,每次在这m个样本中随机采集一个样本,放入训练集,采样完后把样本放回。这样重采集m次,我们得到m个样本组成的训练集。
- 优点:训练集的样本总数和原数据集一样都是 m个,在数据集比较小的时候有用。
- 缺点:这样产生的训练集的数据分布和原数据集的不一样了,会引入估计偏差。
- 实现方法一:自己写算法
>>>import os
>>>import pandas as pd
>>>from random import randint,seed
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>>def bootstrapping(dataset,times=10):
>>> seed(100)
>>> basket_for_splitted_data = []
>>> dataset_copy = list(dataset)
>>> for i in range(times):
>>> train = dataset_copy.copy()
>>> test = dataset_copy[randint(0,len(dataset_copy))]
>>> train.remove(test)
>>> basket_for_splitted_data.append((test,train))
>>> return basket_for_splitted_data
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> basket_for_splitted_data = bootstrapping(data_cases)
>>> for i in range(len(basket_for_splitted_data)):
>>> print(f'第{i+1}组数据:{basket_for_splitted_data[i][0]},{basket_for_splitted_data[i][1][:5]}...')
第1组数据:3.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第2组数据:8.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第3组数据:3067.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第4组数据:132.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第5组数据:35.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第6组数据:2.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第7组数据:78.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第8组数据:32.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第9组数据:1.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
第10组数据:5.0,[1.0, 1.0, 1.0, 1.0, 1.0]...
- 实现方法二:用
pandas
包中的算法
>>>import os
>>>import pandas as pd
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def to_float(data):
>>> # 将数据改为浮点数
>>> for column in data:
>>> if column =='date':continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = to_float(read_csv(file_path))#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> train = data_cases.sample(n=10,replace=True)
>>> for i in range(10):
>>> test= data_cases.loc[data_cases.index.difference([train.index[i]])].copy()
>>> print(f'第{i+1}组数据:{train.values[i]},{test.values}...')
第1组数据:9.0,[ 1. 1. 1. ... 56. 4. 4.]...
第2组数据:11.0,[ 1. 1. 1. ... 56. 4. 4.]...
第3组数据:18.0,[ 1. 1. 1. ... 56. 4. 4.]...
第4组数据:1.0,[ 1. 1. 1. ... 56. 4. 4.]...
第5组数据:0.0,[ 1. 1. 1. ... 56. 4. 4.]...
第6组数据:3.0,[ 1. 1. 1. ... 56. 4. 4.]...
第7组数据:3.0,[ 1. 1. 1. ... 56. 4. 4.]...
第8组数据:27.0,[ 1. 1. 1. ... 56. 4. 4.]...
第9组数据:1.0,[ 1. 1. 1. ... 56. 4. 4.]...
第10组数据:2.0,[ 1. 1. 1. ... 56. 4. 4.]...
5 分层交叉验证(StratifiedKFold)
-
对测试集按类型比例分层,对每层进行无放回抽样。
>>>import os
>>>import pandas as pd
>>>import numpy as np
>>>from sklearn.model_selection import StratifiedKFold
>>>def to_float(func):
>>> def wrapper(*args,**kwargs):
>>> # 将数据改为浮点数
>>> data = func(*args,**kwargs)
>>> for column in data:
>>> if column == 'date': continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>> return wrapper
>>>@to_float
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def startfiledkfold(dataset,k_set=10):
>>> skf = StratifiedKFold(n_splits=k_set)
>>> value = np.array(dataset.values)
>>> target = np.ones([int(dataset.shape[0]),1],int)
>>> return skf.split(value,target)
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = read_csv(file_path)#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> for train,test in startfiledkfold(data_cases):
>>> print(f"train:{train},test:{test}")
train:[ 5655 5656 5657 ... 56538 56539 56540],test:[ 0 1 2 ... 5652 5653 5654]
train:[ 0 1 2 ... 56538 56539 56540],test:[ 5655 5656 5657 ... 11306 11307 11308]
train:[ 0 1 2 ... 56538 56539 56540],test:[11309 11310 11311 ... 16960 16961 16962]
train:[ 0 1 2 ... 56538 56539 56540],test:[16963 16964 16965 ... 22614 22615 22616]
train:[ 0 1 2 ... 56538 56539 56540],test:[22617 22618 22619 ... 28268 28269 28270]
train:[ 0 1 2 ... 56538 56539 56540],test:[28271 28272 28273 ... 33922 33923 33924]
train:[ 0 1 2 ... 56538 56539 56540],test:[33925 33926 33927 ... 39576 39577 39578]
train:[ 0 1 2 ... 56538 56539 56540],test:[39579 39580 39581 ... 45230 45231 45232]
train:[ 0 1 2 ... 56538 56539 56540],test:[45233 45234 45235 ... 50884 50885 50886]
train:[ 0 1 2 ... 50884 50885 50886],test:[50887 50888 50889 ... 56538 56539 56540]
6 留P交叉验证(LeavePOut)
- 与留一交叉验证类似,但是每次留下p个样本做测试集。
>>>import os
>>>import pandas as pd
>>>import numpy as np
>>>from sklearn.model_selection import LeavePOut
>>>def to_float(func):
>>> def wrapper(*args,**kwargs):
>>> # 将数据改为浮点数
>>> data = func(*args,**kwargs)
>>> for column in data:
>>> if column == 'date': continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>> return wrapper
>>>@to_float
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def leave_p_out(dataset,p=10):
>>> # 留P划分
>>> lpo = LeavePOut(p=p)
>>> return lpo.split(dataset)
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = read_csv(file_path)#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> for train,test in leave_p_out(data_cases):
>>> print(f"train:{train},test:{test}")
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35299]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35300]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35301]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35302]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35303]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35304]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35305]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35306]
train:[ 8 10 11 ... 61968 61969 61970],test:[ 0 1 2 3 4 5 6 7 9 35307]
... ...
7 分组交叉验
- 分组交叉验证是为了进一步测试模型的泛化能力,留出一组特定的不属于测试集和训练集的数据。
1) GroupKFold
- k折交叉验证的变体,它确保同一个组在测试和训练集中都不被表示。
- GroupKFold和分层交叉验证比较像,不过测试集是按照一定分组进行打乱的,即先分堆,然后把这些堆打乱,每个堆里的顺序还是固定不变的。
2) LeaveOneGroupOut
- 根据第三方提供的整数组的数组提供的样本。
- 这个组信息可以用来编码任意域特定的预定义交叉验证折叠。
3) LeavePGroupsOut
- 类似于 LeaveOneGroupOut ,只是一个是单组,一个是多组。
4) GroupShuffleSplit
- 是 ShuffleSplit 和 LeavePGroupsOut 的组合,它生成一个随机划分分区的序列,其中为每个分组提供了一组子集。
- 有放回抽样。
>>>import os,random >>>import pandas as pd >>>import numpy as np >>>from sklearn.model_selection import GroupKFold,LeaveOneGroupOut,LeavePGroupsOut,GroupShuffleSplit >>>def to_float(func): >>> def wrapper(*args,**kwargs): >>> # 将数据改为浮点数 >>> data = func(*args,**kwargs) >>> for column in data: >>> if column == 'date': continue # 跳过日期 >>> if str(data[column][1]).isdigit(): # 如果是数字 >>> data[column] = data[column].astype('float') # 将列转为浮点数 >>> return data >>> return wrapper >>>@to_float >>>def read_csv(file): >>> # 获得文件中的数据 >>> return pd.read_csv(file) >>>def group_k_fold(dataset,groups,p=2): >>> gkf = GroupKFold(n_splits=p) >>> return gkf.split(dataset,groups=groups) >>>def leave_one_group_out(dataset,groups): >>> logo = LeaveOneGroupOut() >>> return logo.split(dataset,groups=groups) >>>def leave_p_group_out(dateset,groups,g=2): >>> lpgo = LeavePGroupsOut(n_groups=g) >>> return lpgo.split(dateset,groups=groups) >>>def group_shuffle_split(dataset,groups,n=2): >>> gss = GroupShuffleSplit(n_splits=n) >>> return gss.split(dataset,groups=groups) >>>if __name__ == '__main__': >>> file_path = os.path.join('D:\\','dataset','us-counties.csv') >>> data = read_csv(file_path)# >>> data_cases = data['cases'] # 用新冠案例数做数据 >>> groups = np.array([random.randint(1,5) for x in range(len(data_cases))]) >>> print("GroupKFold:") >>> for train,test in group_k_fold(data_cases,groups): >>> print(f"train:{train},test:{test}") >>> print("\nLeaveOneGroupOut:") >>> for train,test in leave_one_group_out(data_cases,groups): >>> print(f"train:{train},test:{test}") >>> print("\nLeavePGroupOut:") >>> for train, test in leave_p_group_out(data_cases,groups): >>> print(f"train:{train},test:{test}") >>> print("\nGroupShuffleSplit:") >>> for train, test in group_shuffle_split(data_cases,groups): >>> print(f"train:{train},test:{test}") GroupKFold: train:[ 0 2 5 ... 61962 61965 61967],test:[ 1 3 4 ... 61968 61969 61970] train:[ 1 3 4 ... 61968 61969 61970],test:[ 0 2 5 ... 61962 61965 61967] LeaveOneGroupOut: train:[ 0 2 4 ... 61966 61967 61969],test:[ 1 3 11 ... 61964 61968 61970] train:[ 0 1 2 ... 61967 61968 61970],test:[ 4 10 22 ... 61963 61966 61969] train:[ 0 1 2 ... 61968 61969 61970],test:[ 5 6 14 ... 61962 61965 61967] train:[ 0 1 2 ... 61968 61969 61970],test:[ 9 13 18 ... 61943 61950 61956] train:[ 1 3 4 ... 61968 61969 61970],test:[ 0 2 7 ... 61939 61948 61951] LeavePGroupOut: train:[ 0 2 5 ... 61962 61965 61967],test:[ 1 3 4 ... 61968 61969 61970] train:[ 0 2 4 ... 61963 61966 61969],test:[ 1 3 5 ... 61967 61968 61970] train:[ 0 2 4 ... 61966 61967 61969],test:[ 1 3 9 ... 61964 61968 61970] train:[ 4 5 6 ... 61966 61967 61969],test:[ 0 1 2 ... 61964 61968 61970] train:[ 0 1 2 ... 61964 61968 61970],test:[ 4 5 6 ... 61966 61967 61969] train:[ 0 1 2 ... 61967 61968 61970],test:[ 4 9 10 ... 61963 61966 61969] train:[ 1 3 5 ... 61967 61968 61970],test:[ 0 2 4 ... 61963 61966 61969] train:[ 0 1 2 ... 61968 61969 61970],test:[ 5 6 9 ... 61962 61965 61967] train:[ 1 3 4 ... 61968 61969 61970],test:[ 0 2 5 ... 61962 61965 61967] train:[ 1 3 4 ... 61968 61969 61970],test:[ 0 2 7 ... 61950 61951 61956] GroupShuffleSplit: train:[ 0 1 2 ... 61967 61968 61970],test:[ 4 10 22 ... 61963 61966 61969] train:[ 0 1 2 ... 61968 61969 61970],test:[ 9 13 18 ... 61943 61950 61956]
8 时间序列分割(TimeSeriesSplit)
- 时间序列分割是K折交叉的变体, 首先返回 k 折作为训练数据集,并且 (k+1) 折作为测试数据集。
- 另外,它将所有的剩余数据添加到第一个训练分区用来训练模型, 这个类可以用来交叉验证以固定时间间隔察到的时间序列数据样本。
>>>import os
>>>import pandas as pd
>>>from sklearn.model_selection import TimeSeriesSplit
>>>def to_float(func):
>>> def wrapper(*args,**kwargs):
>>> # 将数据改为浮点数
>>> data = func(*args,**kwargs)
>>> for column in data:
>>> if column == 'date': continue # 跳过日期
>>> if str(data[column][1]).isdigit(): # 如果是数字
>>> data[column] = data[column].astype('float') # 将列转为浮点数
>>> return data
>>> return wrapper
>>>@to_float
>>>def read_csv(file):
>>> # 获得文件中的数据
>>> return pd.read_csv(file)
>>>def time_series_split(dataset,n=10):
>>> tscv = TimeSeriesSplit(n_splits=n)
>>> return tscv.split(dataset)
>>>if __name__ == '__main__':
>>> file_path = os.path.join('D:\\','dataset','us-counties.csv')
>>> data = read_csv(file_path)#
>>> data_cases = data['cases'] # 用新冠案例数做数据
>>> for train,test in time_series_split(data_cases):
>>> print(f"train:{train},test:{test}")
train:[ 0 1 2 ... 5638 5639 5640],test:[ 5641 5642 5643 ... 11271 11272 11273]
train:[ 0 1 2 ... 11271 11272 11273],test:[11274 11275 11276 ... 16904 16905 16906]
train:[ 0 1 2 ... 16904 16905 16906],test:[16907 16908 16909 ... 22537 22538 22539]
train:[ 0 1 2 ... 22537 22538 22539],test:[22540 22541 22542 ... 28170 28171 28172]
train:[ 0 1 2 ... 28170 28171 28172],test:[28173 28174 28175 ... 33803 33804 33805]
train:[ 0 1 2 ... 33803 33804 33805],test:[33806 33807 33808 ... 39436 39437 39438]
train:[ 0 1 2 ... 39436 39437 39438],test:[39439 39440 39441 ... 45069 45070 45071]
train:[ 0 1 2 ... 45069 45070 45071],test:[45072 45073 45074 ... 50702 50703 50704]
train:[ 0 1 2 ... 50702 50703 50704],test:[50705 50706 50707 ... 56335 56336 56337]
train:[ 0 1 2 ... 56335 56336 56337],test:[56338 56339 56340 ... 61968 61969 61970]