数据反归一化
- 在数据处理中经常用到归一化将数据缩放到一个较为合理的范围。
- 归一化的方法有很多地方有讲,本篇不做解释
情况1-只对特征进行归一化
将特征和标签,放在相同的数组里,只对特征进行归一化,训练后的模型预测的值,即为最终的值,不需要反归一化。
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import normalize
# 生成数据,100行4列,前三列为特征,最后一列为标签值
a = np.random.randint(1,10,size=(100,3))
b = a[:,0]*0.2+a[:,1]*0.33+a[:,2]*1.3+np.random.randint(1,5,100)
b = b.reshape(100,1)
x = range(100)
co = np.concatenate((a,b),axis=1)
co[:,0] = co[:,0]*93
# 进行归一化
sca = MinMaxScaler()
X = sca.fit_transform(co1[:,0:3])
# 进行模型训练和预测,由于预测值未进行归一化,
model = LinearRegression()
mo =model.fit(X,co1[:,3])
p = mo.score(X, co1[:,3])
pred = mo.predict(X)
plt.figure(figsize=(13,2))
plt.plot(x, co1[:,3],'r')
plt.plot(x, pred,'g')
print(np.sum(abs(pred-co1[:,3]))/100)
# 如果要获取X的原型,使用如下方法即可
X_Ori = sca.inverse_transform(X)
# 后面如果需要对其他样本进行预测,对应的都需要使用该训练好的归一化容器进行设置
x_test = sca.transform(x_test)
预测结果还是可以的平均偏差为0.98
情况2-只对特征和标签同时归一化
对特征和标签同时归一化,使用相同的模型时,效果相对较差,倾向于不对标签值进行归一化,这里对整理归一化作个说明,具体如何选择,在学习中。
特征X 和 标签y同时进行归一化有两种方式,这里是第一种方式,如下所示,把特征和标签当做一个整体,进行归一化fit并transform。最后通过获取该列标签对应的归一化常量,对预测值进行反归一化,
x = range(100)
co2 = co.copy()
sca = MinMaxScaler()
co2 = sca.fit_transform(co2)
model = LinearRegression()
mo =model.fit(co2[:,0:3],co2[:,1])
p = mo.score(co2[:,0:3], co2[:,1])
pred = mo.predict(co2[:,0:3])
plt.figure(figsize=(13,2))
plt.plot(x, co2[:,3],'r')
plt.plot(x, pred,'g')
''' 如下所示第一个图,为归一化后的预测值和实际值"""
同时归一化后预测值和实际值的平均偏差
0.25924477465708706
“”“进行反归一化”""
data1 = sca.inverse_transform(co2)
y = data1[:,3]
y_pred =pred
maxs = sca.data_max_[-1] # 获取原始数据最后一列的最大值
mins = sca.data_min_[-1] # 获取原始数据最后一列的最小值
y_pred = y_pred*(maxs-mins)+mins
plt.figure(figsize=(13,2))
plt.plot(x, y,‘r’)
plt.plot(x, y_pred,‘g’)
print(np.sum(abs(pred-co2[:,3]))/100)`
``
注意:这里的整体数据分布不会改变,只是反归一化后的值需要添加(maxs-mins)的影响
情况3-分别对特征和标签同时归一化
这里是参考stackoverflow中的回答,就是分别进行归一化,定义两个不同的容器分别进行相应的操作。
按理说,sklearn中的归一化的方法是分别对每个特征分别进行操作,所以即使是不同的容器,应该跟上述情况3的结果差异较小,但是,实际操作中,最后的差异还是蛮大的。
x0 = range(100)
co3 = co.copy()
s1 = MinMaxScaler()
s2 = MinMaxScaler()
x = s1.fit_transform(co3[:,0:3])
y = s2.fit_transform(co3[:,3].reshape(100,1))
model = LinearRegression()
mo =model.fit(x,y)
p = mo.score(x,y)
pred = mo.predict(x)
plt.figure(figsize=(13,2))
plt.plot(x0, pred,'r')
plt.plot(x0, y,'g')
print(np.sum(abs(pred-y))/100)
再分别进行反归一化
y0 = s2.inverse_transform(y)
ypre = s2.inverse_transform(pred)
plt.figure(figsize=(13,2))
plt.plot(x0, y0,'r')
plt.plot(x0, ypre,'g')
print(np.sum(abs(y0-ypre))/100)
总结
建议是分别设置2个容器,一个给X,一个给y。也方便最后进行反归一化。
另外也可以选择对某个特征进行反归一化:
sca.inverse_transform(co2)[:,0]
即选择第一列数据反归一化,inverse里的数据是整体数据,就是你当时归一化输入多少维度(这里的维是列数)