该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
刚接触机器学习和矩阵分解,有一个预测矩阵空白数据的需求,比较基础的是采用Funk-SVD,V=WH,但这个分解出来可能有负值。后来看了非负矩阵分解的算法,自己推了一下。模仿NMF取了一个特殊的学习率,把负项削掉了(没有完备的证明),但正常推导效果不好(猜测是步长会变大?)。然后找到一篇博文,上面加了一个对W或H的归一化,效果就好了。也不知道为啥。有哪位大佬懂么?
下附matlab程序
[n m]=size(V);
Va=V;
r=round(0.5*m*n/(m+n))+1; %设置分解矩阵的秩
W=rand(n,r); %初始化WH,为非负数
H=rand(r,m);
P=ones(n,m)-isnan(V);
for i=1:n
for j=1:m
if P(i,j)==0 %空
V(i,j)=1; %任意给一个非空初值
end
end
end
maviter=2000; %最大迭代次数
for iter=1:maviter
% W=W.*((V./(W*H))*H'); %注意这里的三个公式和文中的是对应的
% W=W./(ones(i,1)*sum(W));
% H=H.*(W'*(V./(W*H)));
% W迭代
B=W*H;
for i=1:n
for k=1:r
fz=0;fm=0;
for j=1:m
fz=fz+P(i,j)*V(i,j)*H(k,j);
fm=fm+P(i,j)*H(k,j)*B(i,j);
end
W(i,k)=W(i,k)*fz/fm;
end
end
% W=W./(ones(n,1)*sum(W));
% H迭代
for j=1:m
for k=1:r
fz=0;fm=0;
for i=1:n
fz=fz+P(i,j)*W(i,k)*V(i,j);
fm=fm+P(i,j)*B(i,j)*W(i,k);
end
H(k,j)=H(k,j)*fz/fm;
end
end
H=H./(sum(H)*ones(m,1)); %%%%%这里多了一步归一化
loss=0;
for i=1:n
for j=1:m
if P(i,j)>0 %非空
error = 0;
for k=1:r
error = error+W(i,k)*H(k,j);
end
loss=loss+(V(i,j)-error)*(V(i,j)-error);
end
end
end
if mod(iter,100)==0
iter
loss
end
end
V0=W*H;
re_V=Va;
for i=1:n
for j=1:m
if P(i,j)==0 %空
re_V(i,j)=V0(i,j);
end
end
end