对倾斜数据使用神经网络回归
我多次遇到这个问题,根据我的经验,这是两个最有效的解决方案:
您建议的log(x+1) 转换:您采用
log( x + 1 )
. 这是分布的日志。如果您的因变量有一个下限(即它可能取的最小值),那么我建议您使用log( x + 1 ) + min( x )
. 通过这种方式,您可以将分布限制为仅采用正值,并在输出节点处使用ReLU我最近在工作中尝试过并且效果很好的一种方法是在 1 和 95th percentile 之间进行缩放。此操作类似于更经典的 min-max 缩放,但使用
min(x)
and来计算它max(x)
,你 shringmin(x)
and95th percentile
。我说的95th
是百分位数,但99th
或任何其他也可以很好地工作 - 您可以选择最适合您的任务的一个。当简单的最小-最大缩放不起作用时(即当缩小 0-1 范围内的所有内容会导致较小的观察结果“消失”时),这变得非常有用。最后你会得到一个分布,几乎所有观察都在 0-1 范围内,除此之外几乎没有异常值,对预测的整体质量几乎没有影响。该技术假设ReLU在输出节点激活。通过这种方式,您可以确保始终获得所需的、有意义的范围内的输出。
我尝试了其他技术(一种基于 Sigmoid 函数的上部,以及许多其他基于对数、平方根、标准化和其他单调函数的转换序列),但它们的性能并不比我选择的两种好。当然,这只是基于个人经验。
PS:这些自定义标准化不能依赖sklearn的方法等.fit()
方法。请记住手动将参数保存在特定文件中,否则您将无法将您的发行版恢复为原始版本!
供将来使用:
我遇到了类似的问题。在我的例子中,神经网络无法准确预测数据的偏斜部分。我创建了垃圾箱(在我的情况下为 10 个)并为数据赋予了权重。之后,我在批量梯度下降中使用了重要的采样。这可以使用 keras 生成器轻松完成。
下面是生成器函数。
def generator(features, labels, batch_size, w):
n = features.shape[0]
w = w/w.sum()
while True:
ind = np.random.choice(n,batch_size,p=w)
batch_features = features[ind]
batch_labels = labels[ind]
yield batch_features, batch_labels
该生成器比随机采样更频繁地对倾斜数据进行采样,并确保模型不会偏向于多数数据云。
w
是权重。这是计算权重的蛮力代码。我确信有图书馆可以计算这一点。
data['bins'] = pd.cut(data['response'], [0,1,2,3,4,5,6,7,8,9,10], labels=[1,2,3,4,5,6,7,8,9,10])
weights = data['bins'].value_counts()
weights = 1/weights
weights = weights/sum(weights)
weights = weights.to_dict()
for i in data.index:
data.loc[i,'weights'] = weights[data.loc[i,'bins']]