Numpy函数在不应该更新全局变量时进行更新

2024-06-28 10:51:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在实现一个机器学习算法,它将一个矩阵近似为另外两个矩阵的倍数:V~=WH。W和H是随机初始化的,并且迭代更新,使得WH更像V

在我的代码中,在每次迭代中,我想(I)更新W和H,以及(ii)基于W和H的新值计算一个分数

我的问题是:我用来评分的函数应该只计算一个分数-它不应该影响V、W或H-但它似乎是这样做的!我不知道为什么函数会影响全局变量-我认为只有在声明global foo等形式时才会发生这种情况。结果是,根据是否在每次迭代时计算得分,计算出的W和H之间存在小差异,这没有意义。你知道吗

下面是一些我已经尽可能精简的代码-它没有实现我的算法或做任何有意义的事情,它只是再现了问题,这是有一个小的差异,在计算W的基础上,你是否注释掉了计算分数的行。你知道吗

有人知道为什么这会改变结果吗?你知道吗

import numpy as np

# TRUE, GLOBAL VALUE OF V - should remain the same throughout
V = np.array([[0.0, 4.0, 0.0, 4.0],
              [0.0, 0.0, 1.0, 0.0],
              [4.0, 0.0, 0.0, 3.0]]).astype(float)

# RANDOM INITIALIZATIONS for two matrices, which are then updated by later steps
W = np.array([[ 1.03796229,  1.29098839],
              [ 0.49131664,  0.79759996],
              [ 0.66055735,  0.48055734]]).astype(float)
H = np.array([[ 0.06923306,  0.53105902,  1.1715193,   0.58126684],
              [ 1.71226543,  0.54797385,  0.70978869,  1.58761463]]).astype(float)

# A small number, which is added at some steps to prevent zero division errors/overflows
min_no = np.finfo(np.float32).eps

# A function which calculates SOME SCORE based on V_input - below is the simplest example that reproduces the error
# This function should ONLY calculate and return a score - IT SHOULD NOT UPDATE GLOBAL VARIABLES!
def score(V_input):

    V_input[V_input == 0] = min_no # I believe that THIS LINE may be UPDATING GLOBAL V - but I don't understand why
    scr = np.sum(V_input)

    return scr

# This function UPDATES the W matrix
def W_update(Vw, Ww, Hw):

    WHw = np.matmul(Ww, Hw)
    WHw[WHw == 0] = min_no
    ratio = np.matmul(np.divide(Vw, WHw), np.transpose(Hw))

    return np.multiply(Ww, ratio)

# Repeated update steps
for it in range(10):

    # Update step
    W = W_update(V, W, H)

    # SCORING STEP - A SCORE IS CALCULATED - SHOULD NOT UPDATE GLOBAL VARIABLES
    # HOWEVER, IT APPEARS TO DO SO - SMALL DIFFERENCES BETWEEN FINAL W WHEN COMMENTED OUT/NOT COMMENTED OUT
    score_after_iteration = score(V)

# THE OUTPUT PRINTED HERE IS DIFFERENT DEPENDING ON WHETHER OR NOT THE SCORING STEP IS COMMENTED OUT - WHY?
print(W[:2,:2]) # Just a sample from W after last iteration

Tags: thenowhichinputnpnotfloatsteps
2条回答

如果你传递一个变量,你就传递一个引用到那个对象。因此,如果使用V调用函数,则传递对矩阵V的引用,因此对矩阵的更新就是对该对象的编辑。例如,如果您传递对该列表的引用,然后函数编辑该列表,那么您没有编辑该列表的副本,而是编辑该列表本身,因此可以在调用外部看到这些更改。你知道吗

但是,您可以制作副本,例如:

for it in range(10):

    # Update step
    W = W_update(V, W, H)

    score_after_iteration = score(V.copy())

顺便说一下,W_update也是这样,但这可能不是问题。你知道吗

或者,将score函数更改为不更新其任何输入:

def score(V_input):
    return np.sum(np.where(V_input == 0, min_no, V_input))

相关问题 更多 >