当前位置: 首页 > 工具软件 > Funk > 使用案例 >

非负矩阵分解 matlab,【求问】Funk-SVD如何保障分解矩阵非负

储俊英
2023-12-01

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

刚接触机器学习和矩阵分解,有一个预测矩阵空白数据的需求,比较基础的是采用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

 类似资料: