Преобразовать a для l oop в матричный расчет из np.matmul (1xn, nx1) в np.matmul (mxn, nxm)? - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть проблема линейной алгебры, чтобы преобразовать a для l oop в вычисление матрицы

def f():
    # w.shape = (n,1)
    # X.shape = (m,n)
    # y.shape = (m,)
    # v.shape = (n,n)
    # c is constant
    for t in range(len(X)): 
        x = X[t].reshape((1,-1))
        flag = np.dot(x, w)*y[t]
        cov = np.matmul(np.matmul(x, v), x.T)  # cov is a scalar

        if flag<1:
            b = 1.0/(cov + c)
            a = max(0.0, 1-flag) * b
            w += a*y[t]*np.matmul(v, x.T)
            v -= b*np.matmul(np.matmul(v, x.T), np.matmul(x, v))
    return w, v

Как удалить значение для l oop и заменить его вычислением матрицы?

Ответы [ 3 ]

2 голосов
/ 14 февраля 2020

Вы берете диагональные элементы res1. Таким образом, вы можете использовать $ np.diagonal для извлечения диагональных элементов.

res2 = np.diagonal(np.dot(A[mask], A[mask].T))

Надеюсь, это решит вашу проблему.

1 голос
/ 14 февраля 2020

Давайте подумаем об этом шаг за шагом

def f():
    # w.shape = (n,1)
    # X.shape = (m,n)
    # y.shape = (m,)
    # v.shape = (n,n)
    # c is constant
    for t in range(len(X)): 
        x = X[t].reshape((1,-1))

X is (m, n), x is (n,), преобразованный в (1, n)

        flag = np.dot(x, w)*y[t]

flag - это dot of (1,n) with (n,1) => (1,1) times scalar element of y`; скалярный результат

Как насчет (m, n) X точки с (n, 1) для получения (m, 1)? (X@w)*y[:,None] => (м, 1).

В качестве альтернативы X@w[:,0])*y для создания (м) формы

        cov = np.matmul(np.matmul(x, v), x.T)  # cov is a scalar

matmul/dot x с v, (1, n) с (n, n) => (1, п); и matmul/dot с (n, 1) => (1,1)

Снова с использованием X: X@v (m,n)@(n,n)=>(m,n) Еще одна (n, 1) точка для получения (m, 1)

cov = X@v@X.T


        if flag<1:
            b = 1.0/(cov + c)
            a = max(0.0, 1-flag) * b
            w += a*y[t]*np.matmul(v, x.T)
            v -= b*np.matmul(np.matmul(v, x.T), np.matmul(x, v))

Если flag равен (m, 1) или (m,), мы не можем использовать if. Но мы делаем

 mask = flag < 1
 b = 1.0/(cov[mask]+c                  # (k,) (k less than m)
 a = np.amax(0.0, 1-flag[mask]) * b    # (k,)
 w = np.sum(a*y[mask]*(X[mask,:]@v), axis=?)   # ???
 v ???

Я не проработал детали в последней части. Чтобы было ясно, вы можете назвать X[mask,:], cov[mask], flag[mask], y[mask], так что теперь у вас есть куча массивов (p, n) и (p,).

    return w, v
0 голосов
/ 14 февраля 2020

Я со временем разобрался. Благодаря @ hpaulj

        flag = X@w[:,0]*y #(m,)
        cov = (X[:,None,:]@v@X[:,:,None])[:,0,0] #(m,)

        mask = 1-flag>0   # (p,)

        b = 1.0/(cov[mask]+c)  # (p,)
        a = 1-flag[mask]*b  # (p,)

        tmp1 = a[:,None]*y[mask][:,None]*(X[mask,:]@v) # (p,n)
        w = np.sum(tmp1, axis=0).reshape(w.shape)
        tmp2 = ((v@X.T)@(X@v)).ravel()[:,None]*b  # (n^2,p)
        v = np.sum(tmp2,axis=1).reshape(v.shape)  # (n,n)
...