蒸汽数据赛阶段总结(一)

最近在玩蒸汽工业新人赛,这里总结一下

比赛介绍

这个比赛是阿里天池的新人赛,基本算是数据挖机的入门比赛。数据是火力发电采集到的数据,没有给出数据说明。每条数据给出了38个特征,需要预测目标值。评判预测结果的标准为MSE(mean square error)均方误差。

mse为预测值与真实值之差的平方除以样本数。

比赛链接

思路

拿到题发现,这是一道回归问题,直接预测target值。就先用最简单的线性回归测试了一下。(数据预处理和绘图分析都没做2333)

测完线性回归,从模型扩展(岭回归,Lasso,神经网络),特征处理(PCA,特征缩放,特征选择)两个方向出发,分别寻找更优的方法。实在不行再试试模型融合。

线性回归

这东西也叫最小二乘,线性回归寻找参数wb,使得对训练集与真实的回归目标值y之间的MSE最小。理论推导就不写了,核心代码先列出来。

1
2
3
4
5
6
7
8
9
10
11
'''线性回归'''
X_train, X_test, Y_train, Y_test = train_test_split(X_pca, y, test_size=0.2, random_state=40)
clfL = linear_model.LinearRegression()
clfL.fit(X_train,Y_train)
y_true, y_pred = Y_test, clfL.predict(X_test)
print(mean_squared_error(y_true, y_pred))

ansLiner = clfL.predict(X1_pca)
print(ansLiner.shape)
df = pd.DataFrame(ansLiner)
df.to_csv('./LineR&PCA&Scaler.txt',index=False,header=False)

直接用这个线下可以很高,但是因为数据样本太少,容易过拟合。而且又没有对数据做预处理。所以首先要对数据做预处理,看了一下论坛,发现有人的baseline使用了PCA。

主成分分析(PCA)

PCA将n个特征降维到k个,换句话说对数据进行了降维处理。在降维的同时最大程度上保持了原有数据的信息。PCA在处理过程中不需要人为干预,处理只与原数据相关。

1
2
3
4
5
# PCA数据处理-降维
mypca = PCA(n_components=0.95)
mypca.fit(X)
X_pca = mypca.transform(X)
X1_pca = mypca.transform(zhengqi_test)

使用PCA过后,再利用线性回归进行预测,线上MSE就能达到0.14,但还是没有进榜。

于是开始进行特征分析,绘制数据图像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
plt.figure(figsize=(20, 16))  # 指定绘图对象宽度和高度
colnm = zhengqi_train.columns.tolist()[:39] # 列表头
mcorr = zhengqi_train[colnm].corr() # 相关系数矩阵,即给出了任意两个变量之间的相关系数
mask = np.zeros_like(mcorr, dtype=np.bool) # 构造与mcorr同维数矩阵 为bool型
mask[np.triu_indices_from(mask)] = True # 角分线右侧为True
cmap = sns.diverging_palette(220, 10, as_cmap=True) # 返回matplotlib colormap对象
g = sns.heatmap(mcorr, mask=mask, cmap=cmap, square=True, annot=True, fmt='0.2f') # 热力图(看两两相似度)
plt.show()

# 画正太分布图
sns.distplot(zhengqi_train['target'], fit=norm)
(mu, sigma) = norm.fit(zhengqi_train['target'])
print('\n mu = {:.2f} and sigma = {:.2f}\n'.format(mu, sigma))
plt.legend(['Normal dist. ($\mu=$ {:.2f} and $\sigma=$ {:.2f} )'.format(mu, sigma)], loc='best')
plt.ylabel('Frequency')
fig = plt.figure()
res = stats.probplot(zhengqi_train['target'], plot=plt)
plt.show()

热力图是特征之间的相关性分析,是一个38维的矩阵,保存了两两间相关系数值。然后对target值用正态分布进行极大似然估计,求出对应的mu和sigma值。

这里发现有几个特征相关性特别高,不管是正负相关。相关系数该怎么利用,这是我下一步准备做的。然后观察target的分布,看mu值和sigma值和预测集的进行对比。

岭回归

在特征提取之前,为了得到更好的结果,我开始寻找更好的线性模型。岭回归也是一种用于回归的线性模型。但是在岭回归中,对系数w的选择尽可能的小,即应接近于0。这种约束是正则化的。这种方式对模型做显示约束以避免过拟合,岭回归用到的方法也被称为L2正则化。

1
2
3
4
5
6
7
8
9
'''岭回归'''
X_train, X_test, Y_train, Y_test = train_test_split(X_pca, y, test_size=0.2, random_state=40)
ridge_model = Ridge(alpha=0.1)
ridge_model = RidgeCV(alphas=[0.1, 1.0, 10.0])
ridge_model.fit(X_train,Y_train)
Y_pred = ridge_model.predict(X_test)
print('系数矩阵:\n',ridge_model.coef_)
print('线性回归模型:\n',ridge_model)
print(mean_squared_error(Y_test, Y_pred))

RidgeCV是一种用于自动选择最优的方法,增加会使得系数w更加趋向于0,从而降低训练集性能,但会提升泛化性能。

Lasso

Lasso也是约束系数使得其接近于0,但用到的方法与岭回归不同,叫做L1正则化。即某些系数为0时,特征被模型完全忽略,可以将其看作一种自动化特征选择的方法,更能展示更重要的模型特征。

1
2
3
4
5
6
7
8
'''lasso'''
X_train, X_test, Y_train, Y_test = train_test_split(X_pca, y, test_size=0.2, random_state=40)
lasso_model = Lasso(max_iter=100000)
lasso_model = LassoCV()
lasso_model.fit(X_train,Y_train)
print('最佳的alpha:',lasso_model.alpha_)
Y_pred = lasso_model.predict(X_test)
print(mean_squared_error(Y_test, Y_pred))

如果特征很多,或者只有其中几个是重要的,那么Lasso的效果可能更好。

总结

目前为止,单模型效果最好的方案是PCA+Lasso,线上结果为0.1386。写博客的顺序打算按照我自己的比赛思路来走,所以下一篇将总结使用树模型的GBR,LGB等方法,以及模型融合,特征处理的思路及方法。