[ad_1]

importer date-heure

importer flux tenseur comme tf

importer matplotlib.pyplot comme plt

importer numpy comme np

importer engourdi

définitivement tSNE(X, ndims=2, perplexité=30, la graine=0, max_iter=500, stop_lying_iter=100, maman_switch_iter=400):

“”“L’algorithme t-SNE

Arguments :

X : les coordonnées de grande dimension

ndims : nombre de dimensions dans le domaine de sortie

Retour:

Points de X en petite dimension

“”

élan = 0,5

final_momentum = 0,8

eta = 200,0

N, _RÉ = X.façonner

np.Aléatoire.la graine(la graine)

# normaliser l’entrée

X -= X.moyenne(axe=0) # zéro moyenne

X /= np.abdos(X).maximum() # mise à l’échelle min-max

# calcule la similarité d’entrée pour le t-SNE exact

P = calculGaussienPerplexité(X, perplexité)

# symétriser et normaliser les similarités d’entrée

P = P + P.J

P /= P.somme()

# mentir sur les P-values

P *= 12.0

# initialise la solution

Oui = np.Aléatoire.Randn(N, ndims) * 0,0001

# effectuer la boucle d’entraînement principale

gains = np.ceux_comme(Oui)

uY = np.zeros_like(Oui)

pour je dans Portée(max_iter):

# calculer le gradient, mettre à jour les gains

dY = calculateExactGradient(P, Oui)

gains = np.(np.signe(dY) != np.signe(uY), gains+0,2, gains*0,8).agrafe(0,1)

# mise à jour du gradient avec élan et gains

uY = élan * uY eta * gagne * dY

Oui = Oui + uY

# faire de la solution une moyenne nulle

Oui -= Oui.moyenne(axe=0)

# Arrêtez de mentir sur les valeurs P après un certain temps et changez de rythme

si je == stop_lying_iter:

P /= 12.0

si je == maman_switch_iter:

élan = final_élan

# progression de l’impression

si (je % 50) == 0:

C = évaluerErreur(P, Oui)

à présent = date-heure.date-heure.à présent()

imprimer(F“{maintenant} – Itération {i} : Erreur = {C}”)

retourner Oui

@engourdi.foutre(nopython=Vrai)

définitivement calculateExactGradient(P, Oui):

“”“Gradient de la fonction de coût t-SNE

Arguments :

P : matrice de similarité

Y : coordonnées de faible dimension

Retour:

dY, un tableau numérique de forme (N,D)

“”

N, _RÉ = Oui.façonner

# calcule la matrice de distance euclidienne au carré de Y, la matrice Q et la somme de normalisation

JJ = calculateSquaredEuclideanDistance(Oui)

Q = 1/(1+JJ)

somme_Q = Q.somme()

# calculer le gradient

multiple = (P (Q/somme_Q)) * Q

dY = np.zeros_like(Oui)

pour n dans Portée(N):

pour m dans Portée(N):

si n==m: Continuez

dY[n] += (Oui[n] Oui[m]) * multiple[n,m]

retourner dY

@engourdi.foutre(nopython=Vrai)

définitivement évaluerErreur(P, Oui):

“”“Évaluer la fonction de coût t-SNE

Arguments :

P : matrice de similarité

Y : coordonnées de faible dimension

Retour:

Erreur t-SNE totale C

“”

JJ = calculateSquaredEuclideanDistance(Oui)

# Calculer la matrice Q et la somme de normalisation

Q = 1/(1+JJ)

np.fill_diagonal(Q, np.trouver(np.float32).eps)

Q /= Q.somme()

# Somme erreur t-SNE : somme P log(P/Q)

Erreur = P * np.Journal( (P + np.trouver(np.float32).eps) / (Q + np.trouver(np.float32).eps) )

retourner Erreur.somme()

@engourdi.foutre(nopython=Vrai)

définitivement calculGaussienPerplexité(X, perplexité):

“”“Calculer la perplexité gaussienne

Arguments :

X : tableau numpy de forme (N,D)

perplexité : double

Retour:

Matrice de similarité P

“”

# Calculer la matrice de distance euclidienne au carré

N, _RÉ = X.façonner

JJ = calculateSquaredEuclideanDistance(X)

# Calculer le noyau gaussien ligne par ligne

P = np.zeros_like(JJ)

pour n dans Portée(N):

trouvé = Faux

bêta = 1.0

min_beta = np.inf

max_beta = np.inf

tol = 1e5

# itérer jusqu’à obtenir une bonne perplexité

nitre = 0

pendant que ne pas trouvé et nitre < 200:

# calcule la ligne du noyau gaussien

P[n] = np.exp(bêta * JJ[n])

P[n,n] = np.trouver(np.float32).eps

# calcule l’entropie de la ligne courante

# Gaussiens à normaliser en ligne pour en faire une probabilité

# alors H = somme_i -P[i] log(P[i])

# = somme_i -P[i] (-bêta * DD[n] – log(somme_P))

# = somme_i P[i] * bêta * DD[n] + log(somme_P)

puisard = P[n].somme()

H = bêta * (JJ[n] @ P[n]) / puisard + np.Journal(puisard)

# Évaluer si l’entropie est dans le niveau de tolérance

Hdiff = H np.log2(perplexité)

si tol < Hdiff < tol:

trouvé = Vrai

Pause

si Hdiff > 0:

min_beta = bêta

si max_beta dans (np.inf, np.inf):

bêta *= 2

autre:

bêta = (bêta + max_beta) / 2

autre:

max_beta = bêta

si min_beta dans (np.inf, np.inf):

bêta /= 2

autre:

bêta = (bêta + min_beta) / 2

nitre += 1

# normaliser cette ligne

P[n] /= P[n].somme()

affirmer ne pas np.isnan(P).quelconque()

retourner P

@engourdi.foutre(nopython=Vrai)

définitivement calculateSquaredEuclideanDistance(X):

“”“Calculer la distance au carré

Arguments :

X : tableau numpy de forme (N,D)

Retour:

tableau numpy de forme (N,N) de distances au carré

“”

N, _RÉ = X.façonner

JJ = np.des zéros((N,N))

pour je dans Portée(N1):

pour j dans Portée(je+1, N):

différence = X[i] X[j]

JJ[j][i] = JJ[i][j] = différence @ différence

retourner JJ

(X_train, y_train), (X_test, y_test) = tf.keras.ensembles de données.mnist.load_data()

# choisir 1 000 échantillons dans l’ensemble de données

Lignes = np.Aléatoire.choix(X_test.façonner[0], 1000, remplacer=Faux)

X_données = X_train[rows].remodeler(1000, 1).astype(“flotter”)

X_label = y_train[rows]

# exécutez t-SNE pour transformer en 2D et visualiser en nuage de points

Oui = tSNE(X_données, 2, 30, 0, 500, 100, 400)

plt.chiffre(taille de figue=(8,8))

plt.dispersion(Oui[:,0], Oui[:,1], c=X_label)

plt.Afficher()