在 0 和 1 之间进行归一化,忽略 NaN
Posted
技术标签:
【中文标题】在 0 和 1 之间进行归一化,忽略 NaN【英文标题】:Normalise between 0 and 1 ignoring NaN 【发布时间】:2017-02-07 01:54:58 【问题描述】:对于从x
到y
可能包含NaN
的数字列表,我如何在0 和1 之间进行归一化,忽略NaN
值(它们保持为NaN
)。
通常我会使用来自sklearn.preprocessing
的MinMaxScaler
(ref page),但这不能处理NaN
,并建议根据平均值或中值等来估算值。它不提供忽略所有NaN
值。
【问题讨论】:
使用np.nanmax
和np.nanmin
代替np.max
和np.min
,其余的应该可以正常工作。
所以,基本上:(a-np.nanmin(a))/(np.nanmax(a) - np.nanmin(a))
.
pandas 也可以优雅地处理NaN
s,所以一个简单的(a - a.min()) / (a.max() - a.min())
就可以完成这项工作。
【参考方案1】:
考虑pd.Series
s
s = pd.Series(np.random.choice([3, 4, 5, 6, np.nan], 100))
s.hist()
选项 1 最小最大缩放
new = s.sub(s.min()).div((s.max() - s.min()))
new.hist()
不是 OP 要求的内容 我把这些放进去是因为我想
选项 2 乙状结肠
sigmoid = lambda x: 1 / (1 + np.exp(-x))
new = sigmoid(s.sub(s.mean()))
new.hist()
选项 3 tanh(双曲正切)
new = np.tanh(s.sub(s.mean())).add(1).div(2)
new.hist()
【讨论】:
-1 OP 通过引用MinMaxScaler
明确表示他对线性缩放感兴趣。选项 2 和 3 与 OP 无关,在我看来,这让读者感到困惑,而不是帮助他们。
@user40314 感谢您评论您投反对票的原因。我会用它来改进答案并使其更清晰。
谁曾否决过这个答案。我会很感激解释。这已被修改以提供 OP 想要的并已被接受。
我认为答案很明确,其他选项对寻求更广泛答案的其他读者很有用。【参考方案2】:
这是一种不同的方法,我相信它可以正确回答 OP,唯一的区别是这适用于数据框而不是列表,您可以轻松地将列表放入数据框中,如下所示。其他选项对我不起作用,因为我需要存储 MinMaxScaler 以便在做出预测后进行反向变换。因此,您可以过滤掉目标和输入的 NaN,而不是将整个列传递给 MinMaxScaler。
解决方案示例
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
d = pd.DataFrame('A': [0, 1, 2, 3, np.nan, 3, 2])
null_index = d['A'].isnull()
d.loc[~null_index, ['A']] = scaler.fit_transform(d.loc[~null_index, ['A']])
【讨论】:
这个解决方案很好,但如果必须对多列进行归一化(或者可能必须考虑循环),则不够充分 在我的情况下,每个 MinMaxScaler 对象只需要一列。【参考方案3】:现在(2020 年 6 月)sklearn 的行为似乎符合您(和我)的愿望: np.nan 保持不变。 (主要是从 sklearn 文档复制粘贴)
import sklearn
import numpy as np
from sklearn.preprocessing import MinMaxScaler
sklearn.__version__
# '0.23.1'
data = np.array([[-1, 2, 3], [-0.5, 6,3 ], [np.nan, 18, 3 ]])
print(data)
#[[-1. 2. 3. ]
# [-0.5 6. 3. ]
# [ nan 18. 3. ]]
scaler = MinMaxScaler()
data = scaler.fit_transform(data)
print(data)
#[[0. 0. 0. ]
# [1. 0.25 0. ]
# [ nan 1. 0. ]]
【讨论】:
以上是关于在 0 和 1 之间进行归一化,忽略 NaN的主要内容,如果未能解决你的问题,请参考以下文章