关于归一化报错问题——以Python为例

不少小伙伴在开始数据处理,进行归一化的时候,会出现以下报错问题
ValueError: non-broadcastable output operand with shape (8,1) doesn’t match the broadcast shape (8,6)
本文将讲述报错原因以及如何改正。在改错之前,首先要了解归一化的原理。

归一化介绍

通常,在做数据分析的时候,数据归一化是必不可少的一步,特别是对于多维的数据。Why?,简而言之,数据归一化就是将数据中的每一个元素映射到一个较小的区间,这样,多维数据间的数字差距就会减小,消除量纲的影响。特别是在分析多维数据对标签的影响时更为重要。
常见的归一化方法主要有:

Min-Max
x−minXmaxX−minX\frac{x - minX}{maxX- minX}maxXminXxminX
Min-Max归一化方法将所有的值映射到[0, 1]。

Z-score
x−μσ\frac{x-\mu}{\sigma}σxμ
Z-score方法,其中μ\muμ为处理数据中的均值,σ\sigmaσ为处理数据中的方差。该方法将数据归一化为均值为0,方差为1。对于服从正态分布类的数据而言,适用于该归一化方法。
除上述两种归一化方法,在机器学习中,还有常见的Sigmoid归一化函数、tanh函数……,这里就不一一赘述了。

报错原理

我们以Min-Max归一化方法为例,我们将下面矩阵归一化处理:
[ABCD24560275171243308522439308653499329522499457170439329170765125797796879810059536177672143186318631677] \left[ \begin{matrix} A &B &C &D\\ 245 &602 &751 &712\\ 43 &308 &522 &439\\ 308 &653 &499 &329\\ 522 &499 &457 &170\\ 439 &329 &170 &765\\ 1257 &977 &968 &798\\ 1005 &953 &617 &767\\ 2143 &1863 &1863 &1677 \end{matrix} \right] A24543308522439125710052143B6023086534993299779531863C7515224994571709686171863D7124393291707657987671677

import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
w = pd.read_excel("data.xlsx")
origin = np.array(w)
sc = MinMaxScaler()
data = sc.fit_transform(origin)

处理后得到如下归一化矩阵:

[ABCD0.096190480.189067520.343177790.35965494000.207914940.178500330.126190480.221864950.194329590.105507630.228095240.122829580.1695215600.188571430.0135048200.394824150.578095240.430225080.471352630.416721960.458095240.4147910.264028350.396151291111] \left[ \begin{matrix} A&B&C&D\\ 0.09619048& 0.18906752& 0.34317779& 0.35965494\\ 0 &0 &0.20791494 &0.17850033\\ 0.12619048& 0.22186495 &0.19432959& 0.10550763\\ 0.22809524 &0.12282958 &0.16952156& 0 \\ 0.18857143& 0.01350482 &0 &0.39482415\\ 0.57809524& 0.43022508& 0.47135263 &0.41672196\\ 0.45809524 &0.414791 & 0.26402835& 0.39615129\\ 1 &1 &1 &1 \end{matrix} \right] A0.0961904800.126190480.228095240.188571430.578095240.458095241B0.1890675200.221864950.122829580.013504820.430225080.4147911C0.343177790.207914940.194329590.1695215600.471352630.264028351D0.359654940.178500330.1055076300.394824150.416721960.396151291
根据上面个归一化数据可知,对于数据框,Sklearn库中归一化方法是将数据分列进行处理的。现在,我们将A列数据反归一化。返回原来的值:

#对第一列数据进行反归一化操作
w2 = data[::, 0]
#改变数据维度,不然会报错
w2 = w2.reshape(8, 1)
pr_data = sc.inverse_transform(w2)
print(pr_data)

此时报错:
ValueError: non-broadcastable output operand with shape (8,1) doesn’t match the broadcast shape (8,4)
这是因为我们上面是将一个数据框进行归一化,而当我们在反归一化时只对其中的一列数据进行操作。而程序无法判断我们进行操作的数据对应数据框的哪一列,自然就无法进行反归一化。
注意:从数据框中提取数据需要重新塑造维度,若没有改变数据维度,则会报错:
ValueError: Expected 2D array, got 1D array instead

解决方案

针对以上的报错,这里提供两种解决方法:

1. 用需要反归一化的数据,替换掉历史的数据。

例如现在用A,B,C前三列数据分析D列数据,得到新的一列数据E需要与原数据D进行比较,这时候我们只需要加上两行代码将新数据E代替D列,再反归一化即可。

data = pd.DataFrame(data)
data.iloc[:, 3] = new_data	#新数据列替换D列数据
data = sc.inverse_transform(data)	#反归一化

注意:系统会利用归一化中存储的最值进行反一化操作,因此在反归一化数据是允许出现在[0,1]外的。

2. 自己编写归一化函数

并且实际的数据处理中,对于样本量较小的情况下,调用归一化函数是不合理的。因为小样本数据不符合大数定律,无法客观反映事件的整体特性,即数学语言中的均值,方差,最值等。此时建议对数据归一化处理时所需的数字特征另外获取,并根据数据特性编写归一化代码

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐