我有一个线性代数问题,可以将for循环转换为矩阵计算。
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如何删除for循环并将其替换为矩阵计算?
发布于 2020-02-14 10:13:24
您将获取res1的对角线元素。所以您可以使用$np.diagonal来获取对角线元素。
res2 = np.diagonal(np.dot(A[mask], A[mask].T))希望这能解决你的问题。
发布于 2020-02-14 11:11:27
让我们一步一步地思考这个问题
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是(m,n),x是(n,)重塑为(1,n)
flag = np.dot(x, w)*y[t]flag is dot of (1,n) with (n,1) => (1,1) times scalar element ofy`;结果标量
将(m,n) X点与(n,1)相加,得到(m,1)?(X@w)*y[:,None] => (m,1)。
另一种方法是X@w[:,0])*y以产生(m,)形状
cov = np.matmul(np.matmul(x, v), x.T) # cov is a scalarmatmul/dot x与v,(1,n)与(n,n)=> (1,n);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发布于 2020-02-14 13:22:57
我终于弄明白了。感谢@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)https://stackoverflow.com/questions/60218762
复制相似问题