预测未来销售(二)——数据预处理与特征提取
1、初始化环境
import time # 导入时间模块,用于查看执行过程中所耗费的时间
start_time = time.time()
import numpy as np
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
pd.set_option('display.max_rows', 99) # 在控制台显示dataframe数据最多行数,超过后自动省略
pd.set_option('display.max_columns', 50) # 在控制台显示dataframe数据最多列数,超过后自动省略
2、数据预处理
模型建立的首要过程是将读取数据到程序当中,并对异常数据进行修正或清洗,以便于后续的特征提取与转换。下面笔者从csv数据文件中分别将训练数据和测试数据读入程序中并保存到pandas模块中的DataFrame类型当中。
2.1 销售数据
2.1.1 销售数据读取
从官网提供的sales_train_v2.csv文件中将训练数据提取出来保存在sale_train变量当中。
sale_train = pd.read_csv('%s/sales_train_v2.csv' % data_path)
2.1.2 统计不同ID(shop_id、item_id)下的月销量
根据销售数据sale_train中的日销量,统计出当月的月销量,并将月销量汇入到训练集train_data当中。
Item_Index=['shop_id', 'item_id', 'date_block_num']
data_temp1=sale_train[['shop_id','item_id', 'date_block_num','item_cnt_day']]
train_data=data_temp1.groupby(by=Item_Index)['item_cnt_day'].agg(['sum']).reset_index().rename(columns = {'sum': 'item_cnt_month'})
train_data['item_cnt_month'] = train_data['item_cnt_month'].astype(int).fillna(0)
2.1.3 汇入item_categroy_id属性
从items.csv文件中将item_categroy_id属性汇入到训练集train_data当中。
item = pd.read_csv('%s/items.csv' % data_path)
train_data = train_data.merge(item[['item_id', 'item_category_id']], on = ['item_id'], how = 'left')
2.1.4 修正后的item_cat_id_fix属性
根据item_categories.csv文件的item_category_name字段,对item_categroy_id属性进行修正,将同一个类别不同型号归为同一个类别(根据商品类型名划分(见2.3)),从并将item_categroy_id_fix属性汇入到训练集train_data当中。
item_cat = pd.read_csv('%s/item_categories.csv' % data_path)
item_cat.item_category_name[0]=1
item_cat.item_category_name[1:8]=2
item_cat.item_category_name[8]=3
item_cat.item_category_name[9]=4
item_cat.item_category_name[10:18]=5
item_cat.item_category_name[18:25]=6
item_cat.item_category_name[25]=7
item_cat.item_category_name[26:28]=8
item_cat.item_category_name[28:32]=9
item_cat.item_category_name[32:37]=10
item_cat.item_category_name[37:43]=11
item_cat.item_category_name[43:55]=12
item_cat.item_category_name[55:61]=13
item_cat.item_category_name[61:73]=14
item_cat.item_category_name[73:79]=15
item_cat.item_category_name[79:81]=16
item_cat.item_category_name[81:83]=17
item_cat.item_category_name[83]=18
item_cat=item_cat.rename(columns = {'item_category_name': 'item_cat_id_fix'})
train_data = train_data.merge(item_cat[['item_cat_id_fix', 'item_category_id']], on = ['item_category_id'], how = 'left')
2.2 测试数据
2.2.1 测试数据读取
从官网提供的test.csv文件中将测试数据提取出来保存在sale_train变量当中。
sale_test = pd.read_csv('%s/test.csv' % data_path)
2.2.2 将测试数据汇入测试集当中
将测试文件当中每个ID对应的shop_id和item_id汇入到测试集test_data当中,并将测试集当中的date_block_num赋为34(因为这是要预测2015年11月份的销售量,对应的date_block_num值为34)
test_data=sale_test[['shop_id', 'item_id']]
test_data['date_block_num']=34
2.2.3 汇入item_categroy_id属性
从items.csv文件中将item_categroy_id属性汇入到测试集test_data当中。
item = pd.read_csv('%s/items.csv' % data_path)
train_data = train_data.merge(item[['item_id', 'item_category_id']], on = ['item_id'], how = 'left')
2.2.4 修正后的item_cat_id_fix属性
根据item_categories.csv文件的item_category_name字段,对item_categroy_id属性进行修正,将同一个类别不同型号归为同一个类别(根据商品类型名划分(见2.3)),从并将item_categroy_id_fix属性汇入到测试集test_data当中。
item_cat = pd.read_csv('%s/item_categories.csv' % data_path)
train_data = train_data.merge(item_cat[['item_cat_id_fix', 'item_category_id']], on = ['item_category_id'], how = 'left')
3、特征工程
3.1 汇聚训练数据与测试数据
all_data=pd.concat([train_data,test_data],axis=0)
3.2 提取均值特征
分别计算不同shop、item_id、item_category_id、item_cat_id_fix的每月商品销量的平均值作为特征。
Target = 'item_cnt_month'
mean_encoded_col=[]
from tqdm import tqdm
for col in tqdm(['shop_id', 'item_id', 'item_category_id', 'item_cat_id_fix']):
col_tr = all_data[['date_block_num']+[col]+[Target]]
col_tr=col_tr.groupby(['date_block_num']+[col])[Target].agg('mean').reset_index().rename(columns ={Target:col+'_cnt_month_mean'})
all_data=all_data.merge(col_tr,on=['date_block_num']+[col],how = 'left')
mean_encoded_col.append(col+'_cnt_month_mean')
print(mean_encoded_col)
3.3 提取前月份的各销量特征
提取当前月的前第一个月、前第二个月、前第三个月、前第四个月、前年该月的销量各特征作为特征。
id_col=['shop_id', 'item_id']
index_cols = ['item_category_id', 'item_cat_id_fix', 'date_block_num']
cols_to_rename = mean_encoded_col+[Target]
print(cols_to_rename)
shift_range = [1, 2, 3, 4, 12] # 下一个月、两个月、三个月、四个月和下一年
for month_shift in tqdm(shift_range):
train_shift = all_data[id_col + index_cols + cols_to_rename].copy()
train_shift['date_block_num'] = train_shift['date_block_num'] - month_shift
foo = lambda x: '{}_pre_{}'.format(x, month_shift) if x in cols_to_rename else x
train_shift = train_shift.rename(columns=foo)
all_data = pd.merge(all_data, train_shift, on=id_col+index_cols, how='left').fillna(0)
pre_cols = [col for col in all_data.columns if '_pre_' in col]
all_data = downcast_dtypes(all_data)
3.4 对所有数据进行标准化处理
对所有数据进行标准化处理,为了加快后续"模型"的训练速度。
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
to_drop_cols = ['date_block_num']
feature_columns = list(set(pre_cols + index_cols + list(date_columns)).difference(to_drop_cols))
all_data[feature_columns] = sc.fit_transform(all_data[feature_columns])
3.5 建立训练集和测试集
对将要预测销量的ID号(shop_id+item_id)对风别赋予成第13月到第34月,将train_data与将要预测的有关的数据汇入到数据集all_set之中。
all_set=test[['shop_id','item_id']].copy()
all_set['date_block_num']=np.int8(12)
for i in range(13,35):
data_tmp=sale_test[['shop_id','item_id']].copy()
data_tmp['date_block_num']=np.int8(i)
all_set=pd.concat([all_set,data_tmp],axis=0)
all_set=all_set.merge(all_data,on=['shop_id','item_id','date_block_num'],how='left').fillna(0)
all_set[id_col] = sc.fit_transform(all_set[id_col])
train_set=all_set[all_set['date_block_num']<34][id_col+['item_category_id','item_cat_id_fix']+pre_cols+date_columns]
train_value=all_set[all_set['date_block_num']<34]['item_cnt_month']
test_set=all_set[all_set['date_block_num']==34][id_col+['item_category_id','item_cat_id_fix']+pre_cols+date_columns]
**PS:**从第13月开始,是没有使用2013年的数据,这是因为在特征中使用了前几个月的销售数据特征,而2013年没有 前第12个月的数据,使用2013年的数据就会使数据不完整,所以笔者只使用了2014年后的数据。
PS:最新优化没有同步到博客当中,需要交流的可以邮箱交流:博主邮箱:greatpanc@163.com