Cet article est l'article du 6ème jour de Furukawa Lab Advent_calendar. Cet article a été rédigé par un étudiant du Furukawa Lab dans le cadre de leur apprentissage. Le contenu peut être ambigu ou l'expression peut être légèrement différente.
Depuis que j'ai étudié NMF, je vais l'expliquer d'une manière facile à comprendre. Qu'est-ce que NMF? J'espère que cela aide ceux qui étudient NMF pour la première fois (* ^^) v Dans la seconde moitié, l'état de l'apprentissage est visualisé. NMF(Non-negative Matrix Factorization) NMF décompose la matrice $ Y $ en deux matrices de valeurs non négatives $ W et H $ dans des conditions de contraintes non négatives et les approche. En d'autres termes, cela ressemble à la figure ci-dessous.
Le fait est que les matrices $ Y, W, H, \ hat {Y} $ sont toutes non négatives (pas de valeurs négatives). Autrement dit, $ Y \ geq0, W \ geq0, H \ geq0, \ hat {Y} \ geq0 $. Dans l'algorithme NMF, $ W, H $ est mis à jour afin que $ \ hat {Y} $, qui est le produit interne de $ W, H $, soit aussi proche que possible des données d'origine, $ Y $. Lors de la recherche de la formule de mise à jour, certaines parties sont difficiles à calculer analytiquement, alors remplacez la formule par l'inégalité de Jensen. La formule de mise à jour est répertoriée à la fin. (Lors de l'utilisation de Frobenius)
\begin{equation}
\begin{aligned}
D_{\mathrm{EU}}(\boldsymbol{W}, \boldsymbol{H}) &=\|\boldsymbol{Y}-\boldsymbol{W} \boldsymbol{H}\|_{F}^{2} \\
&=\sum_{m, n}\left|y_{m, n}-\sum_{k} w_{m, k} h_{k, n}\right|^{2}\\
&=\sum_{m, n}\left(\left|y_{m, n}\right|^{2}-2 x_{m, n} \sum_{k} w_{m, k} h_{k, n}+\underset{Difficulté analytique}{\left|\sum_{k} w_{m, k} h_{k, n}\right|^{2}}\right)
\end{aligned}
\end{equation}
\begin{equation}
\lambda_{k, m, n}=\frac{w_{m, k} h_{k, n}}{\sum_{k} w_{m, k} h_{k, n}}
\end{equation}
\begin{equation}
G:=\sum_{m, n}\left(\left|y_{m, n}\right|^{2}-2 y_{m, n} \sum_{k} w_{m, k} h_{k, n}+\sum_{k} \frac{w_{m, k}^{2} h_{k, n}^{2}}{\lambda_{k, m, n}}\right)
\end{equation}
Les deux équations suivantes sont obtenues en différenciant partiellement l'équation ci-dessus. Les optimum $ W et H $ sont obtenus en répétant la formule suivante pour le nombre de temps d'apprentissage.
\begin{equation}
\begin{aligned}
w_{m k} \leftarrow w_{m k} \frac{(\boldsymbol{Y} \boldsymbol{H})_{m n}}{\left(\boldsymbol{W} \boldsymbol{H} \boldsymbol{H}^{T}\right)_{m k}}
\end{aligned}
\end{equation}
\begin{equation}
\begin{aligned}
h_{k n} \leftarrow h_{k n} \frac{\left(\boldsymbol{W}^{T} \boldsymbol{Y}\right)_{m n}}{\left(\boldsymbol{W}^{T} \boldsymbol{W} \boldsymbol{H}\right)_{m n}}
\end{aligned}
\end{equation}
Implémentons NMF en python pour une meilleure compréhension! Ici, nous allons approximer les coordonnées bidimensionnelles avec NMF. La figure de gauche est un tracé de 80 points avec du bruit ajouté à la fonction linéaire. Cette fois, appelons cela les données d'observation $ Y $. Lorsque ces données $ Y $ sont décomposées par NMF et restaurées, le chiffre de droite est obtenu ($ \ hat {Y} $). Vous pouvez bien l'approcher. Ensuite, je vais expliquer à propos de $ W et H $. Dans les coordonnées bidimensionnelles, $ W et H $ peuvent être interprétés comme des poids et des vecteurs de base. Cette fois, $ W $ peut être interprété comme un poids et $ H $ comme un vecteur de base. La figure de droite montre le tracé réel du vecteur de base. En d'autres termes, le point de données peut être exprimé en ajoutant ces deux vecteurs.
Ici, nous allons visualiser l'état de l'apprentissage. ~~ Que signifie visualiser? ~~ La figure de gauche est le point de données créé par la fonction $ cos $. La figure de droite montre l'apprentissage avec NMF.
python code Ce sera le code de l'animation.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anm
import matplotlib.cm as cm
from sklearn.decomposition import NMF
from sklearn import decomposition
np.random.seed(seed=32)
def true_fun(X):
return np.cos(X)**2
X=np.random.rand(80)*4+0.2
Y=true_fun(X)
Y=Y+np.random.normal(0,0.1,80)+1
x=np.zeros([80,2])
x[:,0]=X
x[:,1]=Y
k = 2
m, n = 80, 2
t=0
vecter_x=0,0
vecter_y=0,0
np.random.seed(seed=32)
U = np.abs(np.random.uniform(low=0, high=1, size=(m, k)))
V = np.abs(np.random.uniform(low=0, high=1, size=(n, k)))
xx=np.arange(50)
fig = plt.figure(figsize=(10,4.5))
def update(t):
global U,V
U = U * np.dot(x, V) / np.dot(np.dot(U, V.T), V)
V = V * np.dot(U.T, x).T / np.dot(U.T, np.dot(U, V.T)).T
NMF = np.dot(U, V.T)
print(NMF.shape)
plt.subplot(122)
plt.cla()
plt.title(t)
plt.xlim((0, 4.5))
plt.ylim((0, 3.3))
plt.scatter(NMF[:,0], NMF[:,1],s=60,cmap='blues',color=cm.jet((NMF[:,0]*0.25)),edgecolors='black',linewidths=0.1)
plt.quiver(0,0,V[0,1],V[0,0],angles='xy',scale_units='xy',scale=1)
plt.quiver(0,0,V[0,1],V[1,0],angles='xy',scale_units='xy',scale=1)
plt.subplot(121)
plt.cla()
plt.xlim((0, 4.5))
plt.ylim((0, 3.3))
plt.scatter(X, Y,s=60,cmap='blues',color=cm.jet((x[:,0]*0.25)),edgecolors='black',linewidths=0.1)
ani = anm.FuncAnimation(fig, update,interval = 200, frames = 50)
#ani.save("NMF_cos2.gif", writer = 'imagemagick') #Utilisé lors de la sauvegarde
[1] https://qiita.com/nozma/items/d8dafe4e938c43fb7ad1 [2] http://r9y9.github.io/blog/2013/07/27/nmf-euclid/ [3] https://qiita.com/mamika311/items/d920be626c343bcb423a [4] https://qiita.com/sumita_v09/items/d22850f41257d07c45ea
Recommended Posts