[PYTHON] J'ai lu et implémenté les variantes de UKR

Cet article est le premier 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.

introduction

Dans cet article, j'aimerais vous présenter ce qu'on appelle UKR (Unsupervised Kernel Regression) que j'ai en fait assemblé. Traduit en japonais, il s'agit d'une régression du noyau non supervisée, j'ai lu et implémenté cet article.

Si vous êtes intéressé par l'apprentissage multicorps, essayez-le.

Ce que UKR veut faire

Ce que UKR veut faire, ce sont les données d'observation $ \ mathbf {Y} = (\ mathbf {y} _1, \ mathbf {y} _2, ... \ mathbf {y} _N) \ in \ mathbb {R} ^ {D × Variable latente correspondant à N} $ et à chaque donnée d'observation

$ \ mathbf {X} = (\ mathbf {x} _1, \ mathbf {x} _2, ... \ mathbf {x} _N) \ in \ mathbb {R} ^ {M × N} Le mapping $ \ mathbf {f}: \ mathbb {R} ^ {M} → \ mathbb {R} ^ {D} $ doit être estimé.

Le mappage $ \ mathbf {f} $ est estimé par la formule suivante.

\mathbf{f}(\mathbf{x} ; \mathbf{X})=\sum_{i} \mathbf{y}_{i} \frac{K\left(\mathbf{x}-\mathbf{x}_{i}\right)}{\sum_{j} K\left(\mathbf{x}-\mathbf{x}_{j}\right)}\tag{1}

Peut-être que certaines personnes le connaissent. Cette formule est presque la même que l'estimation de Nadaraya-Watoson. Pour ceux qui ne sont pas familiers, $ K $ dans une expression s'appelle une fonction de noyau et est défini dans cet article avec l'expression suivante.

K\left(\mathbf{x}-\mathbf{x}^{\prime}\right)=\exp \left(\frac{-1}{2h}\left\|\mathbf{x}-\mathbf{x}^{\prime}\right\|^{2}\right)

Cette fonction du noyau est également appelée noyau gaussien. La seule différence avec Nadaraya-Watoson est que la largeur du noyau $ h $ est fixée à 1 $ dans l'article.

La variable latente est mappée à l'espace d'observation par la formule (1), et l'erreur des données d'observation est calculée par la formule suivante.

R(\mathbf{X})=\frac{1}{N} \sum_{i}\left\|\mathbf{y}_{i}-\mathbf{f}\left(\mathbf{x}_{i} ; \mathbf{X}\right)\right\|^{2}\tag{2}

Cette erreur est réduite par la méthode du gradient et la variable latente est mise à jour. Lors de sa mise en œuvre, vous n'avez pas d'autre choix que d'utiliser la différenciation automatique ou d'effectuer vous-même la différenciation et d'écrire la formule dans le programme. Dans cet article, je fais de mon mieux pour utiliser la formule que je me suis différenciée. Si vous écrivez toutes les extensions d'expressions, ce sera assez long et le fardeau pour moi sera grand, donc je ne posterai que le résultat final.

r_{ij}=\frac{K\left(\mathbf{x}_{i}-\mathbf{x}_{j}\right)}{\sum_{j^{\prime}} K\left(\mathbf{x}_{i}-\mathbf{x}_{j^{\prime}}\right)}
\mathbf{d}_{ij}=\mathbf{f}(\mathbf{x}_{j};\mathbf{X})-\mathbf{y}_{i}
\mathbf{\delta}_{ij}=\mathbf{x}_{i}-\mathbf{x}_{j}

En utilisant ces variables, la différenciation de l'équation (2) est exprimée comme suit.

\frac{1}{N} \frac{\partial}{\partial \mathbf{x}_{n}} \sum_{i}\left\|\mathbf{y}_{i}-\mathbf{f}(\mathbf{x}_{i};\mathbf{X})\right\|^{2}=\frac{2}{N}\sum_{i}\left[r_{n i} \mathbf{d}_{n n}^{\mathrm{T}} \mathbf{d}_{n i} \boldsymbol{\delta}_{n i}-r_{i n} \mathbf{d}_{i i}^{\mathrm{T}} \mathbf{d}_{i n} \boldsymbol{\delta}_{i n}\right]

Dans l'ensemble Estimer la cartographie par l'équation (1) Répétez la mise à jour de la variable latente par la méthode du gradient afin que l'erreur soit minimisée dans l'équation (2). Ce sera.

Résultat de la mise en œuvre

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import*
import matplotlib.animation as anm
fig = plt.figure(1,figsize=(14, 6))
ax1 = fig.add_subplot(121,projection='3d')
ax2 = fig.add_subplot(122)
class UKR:
    def __init__(self,N,w,z,D,L):
        self.N = N
        self.zeta = z
        self.x = w
        self.f = []
        self.hist =[]
        self.sigma = 1.0
        self.lamda = 0.1
        self.test = []
        self.lr = 1.0
        self.D = D
        self.L = L
        self.gamma = 1.0 / (self.sigma * self.sigma)
    def fit(self,T):
        self.history = {"z":np.zeros((T, self.N, self.L)),
                        "Y":np.zeros((T, self.N ,self.D))}
        for t in range(T):
            self.delta = self.zeta[:,None,:] - self.zeta[None,:,:]
            self.h_kn = np.exp(-1 / (2*self.sigma ** 2) * np.sum((self.zeta[None, :, :] - self.zeta[:, None, :]) ** 2,axis=2))
            self.g_k = np.sum(self.h_kn,axis=1)
            self.r_ij = self.h_kn/self.g_k[:,None]
            self.f = np.zeros((self.N,self.D))
            self.f = self.r_ij @ self.x
            self.d_ij = self.f[:,None,:] - self.x[None,:,:]
            self.A = self.gamma * self.r_ij * np.einsum('nd,nid->ni', self.f - self.x, self.d_ij)
            self.bibun = np.sum((self.A + self.A.T)[:, :, None] * self.delta, axis=1)
            self.zeta -= self.lr*(self.bibun + self.lamda*self.zeta)
            self.history["Y"][t] = self.f
            self.history["z"][t] = self.zeta

if __name__=="__main__":
    N=20#Le nombre de données
    T=50
    w = np.zeros((N*N,3))
    latent_space=np.random.normal
    zeta = np.dstack(np.meshgrid(np.linspace(-1,1,N),np.linspace(-1,1,N),indexing='ij'))
    zeta = np.reshape(zeta,(N*N,2))
    for i in range (N*N):
        mesh = zeta[i,0]**2-zeta[i,1]**2
        w[i] = np.append(zeta[i],mesh)
    np.random.seed(1)
    i=0
    ukr = UKR(N*N,w,zeta,3,2)
    ukr.fit(T)
    kekka = ukr.history["Y"]
    kekka = np.reshape(kekka,(T,N,N,3))
    k = ukr.history["z"]
    k = np.array(k)
    def update(i, zeta,w):
        print(i)
        ax1.cla()
        ax2.cla()
        ax1.scatter(w[:, 0], w[:, 1], w[:, 2], c=w[:, 0])
        ax1.plot_wireframe(kekka[i,:,:,0],kekka[i,:,:,1],kekka[i,:,:,2])
        ax2.scatter(k[i,:,0],k[i,:,1],c=w[:,0])
        ax1.set_xlabel("X_axis")
        ax1.set_ylabel("Y_axis")
        ax1.set_zlabel("Z_axis")
        ax2.set_title('latentspace')
        ax2.set_xlabel("X_axis")
        ax2.set_ylabel("Y_axis")

    ani = anm.FuncAnimation(fig, update, fargs = (zeta,w), interval = 500, frames = T-1)

    ani.save("test.gif", writer = 'imagemagick')

test.gif

Il s'agit du résultat de la mise en œuvre lorsque les données de type selle sont données comme données d'observation. La figure de gauche montre l'espace d'observation, où chaque point montre les données d'observation et la variété qui relie les données mappées. La figure de droite montre l'espace latent.

C'est bien que les variétés couvrent progressivement les données d'observation, il est difficile de se lasser de les voir.

Les références

Variants of unsupervised kernel regression: General cost functions

Recommended Posts

J'ai lu et implémenté les variantes de UKR
J'ai lu l'implémentation de range (Objects / rangeobject.c)
J'ai vérifié les versions de Blender et Python
J'ai vérifié le système d'exploitation et le shell par défaut de docker-machine
J'ai lu "Bases des circuits électriques et des lignes de transmission"
J'ai lu l'article de SHAP
J'ai essayé d'implémenter l'algorithme FloodFill avec TRON BATTLE de CodinGame
J'ai affiché le chat de YouTube Live et essayé de jouer
J'ai implémenté N-Queen dans différentes langues et mesuré la vitesse
L'histoire de Python et l'histoire de NaN
J'ai étudié le mécanisme de connexion flask!
Exécutez Pylint et lisez les résultats
J'ai comparé la vitesse de Hash avec Topaz, Ruby et Python
Je veux lire la version html de la version "OpenCV-Python Tutorials" OpenCV 3.1
Lisez l'image du jeu de puzzle et sortez la séquence de chaque bloc
[Python] J'ai expliqué en détail la théorie et la mise en œuvre de la régression logistique
[Python] J'ai expliqué en détail la théorie et la mise en œuvre de l'arbre de décision
J'ai étudié le comportement de la différence entre lien dur et lien symbolique
J'ai remplacé le calcul numérique de Python par Rust et comparé la vitesse
J'ai vérifié le contenu du volume du docker
J'ai essayé le serveur asynchrone de Django 3.0
Ceci et celui de la notation d'inclusion.
J'ai lu le dictionnaire de synonymes Sudachi avec Pandas et essayé de rechercher des synonymes
J'ai essayé de visualiser la tranche d'âge et la distribution des taux d'Atcoder
Ce que j'ai fait pour garder une trace de l'humidité et de la température des archives
Revoir le concept et la terminologie de la régression
Je ne connaissais pas les bases de Python
J'ai vectorisé l'accord de la chanson avec word2vec et je l'ai visualisé avec t-SNE
Je vois, je vais lire le processus UNIX
J'ai essayé d'extraire et d'illustrer l'étape de l'histoire à l'aide de COTOHA
Lisez l'image du graphique avec OpenCV et obtenez les coordonnées du point final du graphique
J'ai essayé de vérifier et d'analyser l'accélération de Python par Cython
L'histoire d'essayer deep3d et de perdre
Je veux analyser les sentiments des gens qui veulent se rencontrer et trembler
Lire tout le contenu de proc / [pid]
J'ai vérifié le nombre de magasins fermés et ouverts dans tout le pays par Corona
Lire l'implémentation de la minuterie globale ARM
J'ai mesuré la vitesse de la notation d'inclusion de liste, pendant et pendant avec python2.7.
J'ai implémenté le modèle VGG16 avec Keras et essayé d'identifier CIFAR10
J'ai essayé de notifier la mise à jour de "Hameln" en utilisant "Beautiful Soup" et "IFTTT"
Parlez des fonctionnalités dont les pandas et moi étions en charge dans le projet
J'ai comparé la vitesse des expressions régulières en Ruby, Python et Perl (version 2013)
J'ai tweeté l'éclairement de la pièce avec Raspberry Pi, Arduino et un capteur optique
[Python] J'ai expliqué en détail la théorie et l'implémentation de la machine à vecteurs de support (SVM).
J'ai comparé la moyenne mobile du type de filtre IIR avec les pandas et scipy
J'ai essayé la fonction de tableau croisé dynamique des pandas
[Python] Lire le code source de Bottle Part 2
J'ai essayé l'analyse par grappes de la carte météo
À propos du comportement de copy, deepcopy et numpy.copy
Résumé des différences entre PHP et Python
J'ai implémenté DCGAN et essayé de générer des pommes
Compréhension complète des concepts de Bellmanford et Dyxtra
J'ai résolu le problème le plus profond d'Hiroshi Yuki.
La réponse de "1/2" est différente entre python2 et 3
Spécification de la plage des tableaux ruby et python
J'ai vérifié la liste des touches de raccourci de Jupyter
Changer la couleur des erreurs et avertissements Fabric