Home > Blockchain >  Cleaner way to fill matrix based on other matrix values
Cleaner way to fill matrix based on other matrix values

Time:10-01

Let's suppose we have these two matrices

epsilon = np.asmatrix([
    [1,2],
    [-1,2],
    [0,2]
])

and this one:

step_weights = np.asmatrix(np.random.normal(0, 0.5, (np.shape(epsilon)))

I want to populate/update step_weights matrix based on epsilon values, that is:

if epsilon[i,j] > 0:
    step_weights[i,j] = np.minimum(1.2 * step_weights[i,j], 50)
elif epsilon[i,j] < 0:
    step_weights[i,j] = np.maximum(0.5 * step_weights[i,j], 10**-6)

This is what I have done:

import numpy as np

def update_steps(self, epsilon):
    for (i, j), epsilon_ij in np.ndenumerate(epsilon):
        if epsilon_ij > 0:
            step_weights[i, j] = np.minimum(1.2 * step_weights[i,j], 50)
        elif epsilon_ij < 0:
            step_weights[i, j] =np.maximum(0.5 * step_weights[i,j], 10**-6)

and that's working fine.

My question is: is there a more efficient/cleaner way to do it, avoiding the for loop? For example exploiting matrix calculus or linear algebra?

CodePudding user response:

Use bool indices array:

>>> np.random.seed(0)
>>> step_weights = np.asmatrix(np.random.normal(0, 0.5, np.shape(epsilon)))
>>> step_weights
matrix([[ 0.88202617,  0.2000786 ],
        [ 0.48936899,  1.1204466 ],
        [ 0.933779  , -0.48863894]])
>>> mask = epsilon > 0
>>> step_weights[mask] = np.minimum(step_weights.A[mask] * 1.2, 50)
>>> mask = epsilon < 0
>>> step_weights[mask] = np.maximum(step_weights.A[mask] * 0.5, 10 ** -6)
>>> step_weights
matrix([[ 1.05843141,  0.24009433],
        [ 0.2446845 ,  1.34453592],
        [ 0.933779  , -0.58636673]])

Note: The matrix class is not recommended now, and will be discarded in the future. It should use a regular multidimensional array instead. The current multidimensional array already supports many matrix operations (such as using the @ operator for matrix multiplication).

  • Related