Python:使用上限重新分配权重

Posted

技术标签:

【中文标题】Python:使用上限重新分配权重【英文标题】:Python: reallocate weights with a cap 【发布时间】:2022-01-11 21:11:41 【问题描述】:

如何重新分配标准化数据帧的权重并设置上限。

例如,如果我有以下一行数据:

0.1 0.3 0.5 0.1

我不希望任何大于 0.4 的权重。如何裁剪 0.5 权重并重新分配权重,以便最大化每个条目。所以我会得到:

0.1 0.4 0.4 0.1

因此,将 0.5 裁剪为 0.4,将剩余的 0.1 添加到 0.3 得到 0.4。 请注意,在这两种情况下,条目总和为 1(标准化)。

这可以通过python来完成吗?即没有循环。

理想情况下,我希望将其应用于这样的数据框:

df = pd.DataFrame('a': [5003, 54.06, 53.654, 55.2], 'b': [np.nan, 54.1121, 53.98, 55.12], 'c': [np.nan, 2, 53.322, 54.99],
               'd': [np.nan, 53.1, 53.212, 55.002], 'e': [np.nan, 53, 53.2, 55.021], 'f': [np.nan, 53.11, 53.120, 55.3])
N = 5 # 1/np.sqrt(N) = 0.447214
df = df.div(df.sum(axis=1), axis=0)
df:
        a           b            c          d           e           f
    0   1.000000    NaN          NaN        NaN         NaN         NaN
    1   0.200681    0.200875    0.007424    0.197118    0.196747    0.197155
    2   0.167413    0.168431    0.166378    0.166034    0.165997    0.165747
    3   0.166952    0.166711    0.166317    0.166354    0.166411    0.167255

谢谢。

【问题讨论】:

我不知道如何回答这个问题,但我想更好地理解问题参数。在您的示例中,为什么将 0.1 分配给第二个条目?在更大数组的更一般情况下应该如何决定? 它应该按降序分配,以便您最大化每个条目。另一个例子是,如果我们有这一行: 0.01 0.5 0.45 0.04 那么 0.5 将被剪裁为 0.4,0.45 将被剪裁为 0.4,剩下的 0.15 将分配如下: 0.15 到 0.04(因为它是下一个最大的数字),我们会得到:0.01 0.4 0.4 0.19 【参考方案1】:

当我使用它时,它会起作用,但如果你发现它坏了,我肯定很想知道。总体思路是将其融合为长格式数据帧,以允许 groupby 操作避免显式循环

import pandas as pd
import numpy as np

#Df from your example
df = pd.DataFrame('a': [5003, 54.06, 53.654, 55.2], 'b': [np.nan, 54.1121, 53.98, 55.12], 'c': [np.nan, 2, 53.322, 54.99],
               'd': [np.nan, 53.1, 53.212, 55.002], 'e': [np.nan, 53, 53.2, 55.021], 'f': [np.nan, 53.11, 53.120, 55.3])

df = df.div(df.sum(axis=1), axis=0).fillna(0) #assume the nulls should be zeros so we can add to them

nrows,ncols = df.shape
min_cap = 1/ncols #note that the cap has to be at the very least larger than this value for rows to sum to 1

cap = 0.2 #just using 0.2 as an example

#convert to long form to allow for groupbys
long_df = df.reset_index().melt(id_vars=['index']).set_index(['index','variable'])['value']

#calculate excess per row and cap the overfilled entries
excess = long_df[long_df.ge(cap)].sub(cap).groupby('index').sum()
long_df[long_df.ge(cap)] = cap

#fill underfilled entries than can be completely filled
fill_space = cap-long_df
cumsum_fill = fill_space.sort_values().groupby('index').cumsum()
full_fill = excess.ge(cumsum_fill)
long_df[full_fill] = cap

#add remaining fill to largest elements of each row
final_excess = excess-cumsum_fill[full_fill].groupby('index').max()
ind_last_excess = long_df[long_df.lt(cap)].groupby('index').idxmax()
long_df[ind_last_excess] += final_excess

#pivot back to the same df shape as original
res_df = long_df.reset_index().pivot_table(values='value',index='index',columns='variable').fillna(0)
print(res_df)

输出:

variable         a         b         c         d         e         f
index                                                               
0         0.200000  0.200000  0.000000  0.200000  0.200000  0.200000
1         0.200000  0.200000  0.007424  0.197118  0.196747  0.198711
2         0.167413  0.000000  0.166378  0.166034  0.165997  0.165747
3         0.166952  0.166711  0.166317  0.166354  0.166411  0.000000

【讨论】:

如何为数据帧而不是数组做到这一点?我试图编辑现有代码但没有用。谢谢! 您可以编辑您的问题并发布您的 df 负责人的样子吗? 我提供了一个新答案 效果很好。但是在第一行中,为什么 c 列的条目为零?由于 b、c、d、e、f 的条目是相同的(NaN),我希望权重在所有这些条目中平均分配。是否有对此的解释以及任何方法可以使如果条目相等,则裁剪后的权重将在它们之间平均分配? 很抱歉,我不知道如何为关系添加新逻辑。我认为该方法将包括一个新的 groupby 将关系组合在一起并遍历它们。祝你好运!

以上是关于Python:使用上限重新分配权重的主要内容,如果未能解决你的问题,请参考以下文章

如何手动为 SVM 中的某些特征分配权重?

将权重分配给多标签 SVM 以平衡类别

如何在 Keras 中重新初始化现有模型的层权重?

迭代重新加权最小二乘

AppDomain 的 CPU 和内存上限

Android布局权重是怎样的