[PYTHON] Science "Saito est-il le représentant de Saito?"

Problème de Saito

Que faire

"Saito" reconnu comme un kanji

  • 4 types (2 nouvelles polices, 2 anciennes polices). Selon Oriental Economy Online
  • ① Saito est la source,
  • ② Saito est l'ancienne police de caractères de la source (①).
  • ③ Saito a fait une erreur en écrivant la nouvelle police (①). (Fait étonnant 1)
  • ④ Saito a fait une erreur en écrivant l'ancienne police (②). (Fait étonnant # 2
  • La population au Japon entre parenthèses ci-dessous est ** ①, qui est la plus grande, et Saito est la source **.
Nouvelle police Ancienne police
La source ①U+658E (542,000 personnes)
33.jpg
<fontcolor=red>Lasource
②U+9F4B(86,800personnes)
13.jpg
Lasource(①)Ancienne police
En réalité,
L'écritureerreur
③U+6589(323,000 personnes)
32.jpg
Lasource(①)のL'écritureerreur
④U+9F4A(37,300personnes)
2.jpg
Anciennepolice(②)のL'écritureerreur

Et émotionnellement

Après tout, je veux que ** "Sai" ** ((1) source) soit ** représentatif (au milieu) ** de tous les caractères Sai (4 types).

Alors vérifions

  • Je veux faire une carte Saito pour confirmer le ** représentant (au milieu) ** de Saito.
  • Par contre, l'image utilisée est de 58x58 = 3364 pixels (3364 dimensions) et ne peut pas être mappée aux coordonnées XY (2 dimensions).
  • Par conséquent, j'aimerais utiliser une technique appelée ** compression de dimension ** pour compresser en ** 3,364 dimensions ⇒ 2 dimensions **.
  • La compression dimensionnelle des caractères est traitée dans cet article, je vais donc y faire un lien.
  • Cette fois, ** UMAP ** est utilisé comme algorithme de compression de dimension.

image.png

  • Ensuite, compressez dimensionnellement avec UMAP.
from umap import UMAP
# Umap decomposition
decomp = UMAP(n_components=2,random_state=42)
# fit_transform umap(Données de caractères Saito 4)
embedding4 = decomp.fit_transform(all.T[[1,12,31,32]])

Vérification 1) Déterminer les représentants des quatre Saito

  • En utilisant UMap, mappez ** image Kanji ** en ** 2D (avion) ** et cochez ** «Représentant» **.
  • Regardons le ** "centre de gravité" pour toutes les données comme le "représentant" **, pas le "centre" (0,5, 0,5).
  • Le "centre de gravité" est représenté par la marque ** x **, mais qu'en est-il? .. (C'est en dessous du centre de gravité x.)
from sklearn.cluster import KMeans

#clustering (1 cluster)
clustering = KMeans(n_clusters=1,random_state=42,)
# fit_predict cluster
cl_y = clustering.fit_predict(embedding4)

# visualize (La mise en œuvre sera décrite plus tard)
showScatter(
    embeddings    = embedding4,
    clusterlabels = cl_y,
    centers       = clustering.cluster_centers_,
    imgs          = all.T[[1,12,31,32]].reshape(-1,h,w)
)

image.png

  • ** C'est subtil, **
  • Lors du calcul de la distance euclidienne du "centre de gravité" à "chaque caractère", cela ressemble à ceci.
  • Dans ce résultat, ** ② source (ancienne police) épée ** est devenu le représentant. ..
Par ordre de proximité du centre de gravité lettre Distance du centre de gravité Note
1ère place 13.jpg 0.6281 ②Source(anciennepolice)
2ème place 32.jpg 0.6889 ③Erreur(nouvellepolice)
3ème place 33.jpg 0.7339 ①Source(nouvellepolice)
4e place 02.jpg 0.8743 ④Erreur(anciennepolice)

Vérification 2) Déterminer le "représentant" de 33 Saito

Au fait, combien de types de Saito existe-t-il?

  • Il n'y a que quatre types de kanji, mais pour dire la vérité, selon wikipedia
  • Il existe 31 modèles de caractères variantes autres que "Sai, Sai".
  • D'un autre côté, le Ministère de la Justice ne reconnaît que quatre personnages Sai, "Sai, Sai, Sai, Sai".
  • En d'autres termes, ** Sur les 33 modèles, seuls 4 sont acceptés comme Kanji **
  • En plus de Saito, qui est reconnu comme un kanji, j'aimerais voir ** des "représentants" des 33 Saito **

image.png

  • Maintenant, compressons les dimensions de 33 caractères avec UMAP.
from umap import UMAP
# Umap decomposition
decomp = UMAP(n_components=2,random_state=42)
# fit_transform umap(Toutes les données de 33 caractères)
embeddings = decomp.fit_transform(all.T)

Quel est le "représentant" des 33 "Saito"?

  • De même, effectuez une compression de dimension avec UMAP et vérifiez le kanji qui est proche du "centre de gravité".
from sklearn.cluster import KMeans
# clustering(Nombre de clusters: 1)
clustering = KMeans(n_clusters=1, random_state=42)
# fit_predict cluster
cl_y = clustering.fit_predict(embeddings)
# visualize
showScatter(embeddings, cl_y, clustering.cluster_centers_)
download.png
Au lieu du "sai" attendu, est proche du représentant (au milieu). ..
  • L'ordre de distance par rapport au centre de gravité (en haut) est le suivant. Ww qui ne se passe pas comme prévu
Par ordre de proximité du centre de gravité lettre Distance du centre de gravité Note
1ère place 28.jpg 0.494
2ème place 30.jpg 0.787
3ème place 27.jpg 1.013
4e place 31.jpg 1.014

Vérification 3) Sélectionnez 4 caractères du représentant "Saito"

  • "Don't middle" ne fonctionnait pas, mais ** 4 types ** sont acceptés comme kanji.
  • Ensuite, le kanji sur cette carte est divisé en 4 clusters, et quel kanji est le centre de gravité de chaque cluster?
  • En d'autres termes, je voudrais sélectionner et voir les 4 caractères représentatifs ** parmi les 33 caractères.
  • En utilisant l'algorithme de clustering KMeans, il est divisé en 4 clusters comme indiqué ci-dessous.
from sklearn.cluster import KMeans
# clustering(Nombre de clusters: 4)
clustering = KMeans(n_clusters=4, random_state=42)
# fit_predict cluster
cl_y = clustering.fit_predict(embeddings)
# visualize
showScatter(embeddings, cl_y, clustering.cluster_centers_)
download.png
  • Les caractères de chaque groupe et les caractères proches du centre de gravité sont les suivants.
  • D'une manière ou d'une autre, cela semble être un groupe qui capture les caractéristiques des kanji (mois et indication).
  • Les points proches du centre du cluster capturent-ils les caractéristiques du cluster? Est subtile.
  • 4 Il ne peut pas être classé comme un cluster et red cluster </ font> contient plusieurs motifs.
  • Il semble que nous devions le classer un peu plus **
  • Si vous jetez un coup d'œil rapide, il semble que si vous avez ** fois 8 clusters **, vous pourrez le diviser magnifiquement.
No grappe Centre de gravité Autres personnages inclus
1 rouge 25.jpg 19.jpg33.jpg20.jpg21.jpg 27.jpg28.jpg 30.jpg31.jpg
2 Orange 26.jpg 13.jpg14.jpg15.jpg16.jpg17.jpg18.jpg22.jpg23.jpg24.jpg
3 Bleu 29.jpg 10.jpg32.jpg 11.jpg
4 vert 08.jpg 01.jpg02.jpg03.jpg04.jpg05.jpg06.jpg07.jpg08.jpg 12.jpg

Vérification 4) 8 Essayez le clustering

  • Auparavant, il y avait 4 groupes pour sélectionner 4 caractères kanji représentatifs.
  • Cependant, en regardant les résultats, il y avait certains clusters qui ne pouvaient pas être séparés proprement, donc définissons le nombre de clusters sur 8.
  • Les résultats sont les suivants.
from sklearn.cluster import KMeans
# clustering(Nombre de clusters: 8)
clustering = KMeans(n_clusters=8, random_state=42)
# fit_predict cluster
cl_y = clustering.fit_predict(embeddings)
# visualize
showScatter(embeddings, cl_y, clustering.cluster_centers_)
download.png
  • Ce n'est pas qu'ils sont séparés proprement, mais on a l'impression qu'ils ont été triés.
No grappe grappeに含まれる字
1 pêche 13.jpg15.jpg33.jpg18.jpg
2 rouge 14.jpg22.jpg24.jpg26.jpg
3 thé 16.jpg17.jpg23.jpg
4 Cendre 30.jpg31.jpg 28.jpg
5 Orange 19.jpg20.jpg21.jpg25.jpg 27.jpg
6 Bleu 10.jpg32.jpg29.jpg
7 violet 11.jpg12.jpg01.jpg
8 vert 02.jpg03.jpg04.jpg05.jpg06.jpg07.jpg08.jpg09.jpg
  • Malheureusement, orange </ b> </ font>![27.jpg](https: //qiita-image-store.s3.ap-northeast-1) .amazonaws.com / 0/183826 / 666133d0-3d55-6c0a-de96-ef8ab943afbe.jpeg) et gray </ b> </ font>![28.jpg] Sur (https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/0ba6a86b-3e46-d8a4-d2ac-6443ecda4d83.jpeg), le cluster est cassé.
  • Cependant, puisque les deux sont des données sur la limite du cluster, mes pensées peuvent être transmises (rires). image.png

Vérification 5) Vérifiez combien de clusters sont valides

  • 4 groupes pour correspondre aux 4 caractères enregistrés comme kanji.
  • Ensuite, en regardant les résultats de 4 clusters, j'ai essayé de les séparer en 8 clusters.
  • Vraiment, ** Combien de grappes convient-il? ** **
  • Ici, comme méthode de sélection du nombre de clusters, je voudrais visualiser et examiner l'état des clusters en utilisant les trois méthodes suivantes.
  1. Elbow Chart
  2. Silhouette Chart
  3. dendrogram

Elbow Chart

  • Le graphique en coude est un diagramme avec ** la variation des données dans chaque cluster ** sur l'axe vertical et ** le nombre de clusters ** sur l'axe horizontal.
  • Vous pouvez réduire la variation en augmentant le nombre de clusters, mais c'est aussi un problème qu'il y ait trop de clusters.
  • Par conséquent, ** le nombre de clusters ** et ** le nombre de clusters qui peuvent supprimer la variation des données ** sont pris en compte dans cette figure.
  • Pour le dessin, nous utiliserons Yellowbrick.
from yellowbrick.cluster import KElbowVisualizer
vis = KElbowVisualizer(
    KMeans(random_state=42),
    k=(1,34) #Nombre de clusters (plage sur l'axe horizontal))
)
vis.fit(embeddings)
vis.show()
download.png
  • Le sentiment que vous voyez est
  • Jusqu'à 5 grappes, ** la variabilité des données (moyenne) a diminué **, mais par la suite elle est devenue stable.
  • Par conséquent, ** classé en 5 groupes ** semble être bon = le kanji représentatif est ** 5 types ** semble être bon.
  • Mais jetons un coup d'œil à la version agrandie (agrandie de 4-18)
  • Il semble y avoir un tournant dans 5, mais il est devenu plat à partir de ** environ 10 **.
  • En d'autres termes, il semble qu'il n'y ait pas d'erreur en ** classant en 8 groupes et en décidant 8 kanji représentatifs **.
from yellowbrick.cluster import KElbowVisualizer
vis = KElbowVisualizer(
    KMeans(random_state=42),
    k=(4,19) #Nombre de clusters (plage sur l'axe horizontal))
)
vis.fit(embeddings)
vis.show()
download.png

Silhouette Chart

  • Silhouette Chart est un diagramme qui exprime ce qui suit pour chaque cluster.
  • Axe vertical (épaisseur du graphique): nombre d'échantillons dans le cluster
  • Axe horizontal (longueur du graphique): coefficient de silhouette du cluster
  • Ligne brisée: coefficient de silhouette moyen
  • Du point de vue, il s'agit de trouver le nombre de Glasta qui satisfait ce qui suit.
  • Même nombre d'échantillons pour toutes les grappes = même épaisseur
  • Le coefficient de silhouette de tous les Glasta est proche de la moyenne = la longueur est proche de la ligne brisée
  • De même, Yellowbrick sera utilisé pour le dessin.
from yellowbrick.cluster import silhouette_visualizer
fig = plt.figure(figsize=(15,25))
#Dessinez ensemble de 4 à 9 grappes
for i in range(4,10):
    ax = fig.add_subplot(4,2,i-1)
    silhouette_visualizer(KMeans(i),embeddings)
  • Comme vous pouvez le voir, le motif en haut à droite (** 5 groupes) est agréable. download.png

dendrogram

  • C'est un graphique qui exprime la ** proximité ** entre les clusters comme une table de tournoi.
  • Puisqu'il s'agit d'un diagramme qui peut être utilisé dans le clustering hiérarchique, le clustering hiérarchique de Scipy est utilisé à la place des KMeans.
  • La vue est la suivante.
  • Des grappes avec des feuilles comme données et des branches de la même couleur avec la même gamme
  • La hauteur est la distance entre les grappes
from scipy.cluster.hierarchy import linkage, dendrogram
Z = linkage(
    y = embeddings,
    method = 'weighted',
    metric = "euclidean",
)

R = dendrogram(
    Z=Z,
    color_threshold=1.2, #Ajuster le nombre de clusters avec ce seuil
    show_contracted=False,
)
  • ** Ce serait bien que le nombre de branches de chaque couleur soit bien équilibré et que les hauteurs soient les mêmes. Après tout, le nombre de grappes est-il d'environ 5?
Nombre de clusters Dendrogramme commentaire
download.png rougeJuste un peu cher
download.png La hauteur est uniforme
violetJe m'inquiète pour quelques-uns
Ça fait du bien
download.png La hauteur et le nombre sont les mêmes,
Est-il divisé trop finement?

Vérification 6) Essayez de faire 5 clusters

  • Depuis que j'ai examiné le nombre de clusters, j'aimerais à nouveau tracer à quoi il ressemblera avec 5 clusters.
  • Sonne plutôt bien. Après tout, s'agit-il de 5 groupes?
from sklearn.cluster import KMeans
# clustering(Nombre de clusters: 5)
clustering = KMeans(n_clusters=5, random_state=42)
# fit_predict cluster
cl_y = clustering.fit_predict(embeddings)
# visualize
showScatter(embeddings, cl_y, clustering.cluster_centers_)
download.png
No grappe Centre de gravité Autres personnages inclus
1 Bleu 15.jpg 13.jpg14.jpg33.jpg18.jpg
2 violet 23.jpg 16.jpg17.jpg22.jpg24.jpg26.jpg21.jpg
3 vert 27.jpg 19.jpg20.jpg25.jpg 27.jpg28.jpg 30.jpg31.jpg
4 rouge 29.jpg 32.jpg10.jpg 11.jpg
5 Orange 08.jpg 01.jpg02.jpg03.jpg04.jpg05.jpg06.jpg07.jpg09.jpg 12.jpg

Résumé

Impressions

  • En tant que flux,
  • Commencez par sélectionner un représentant de 4 caractères enregistrés comme Kanji
  • Pour les 33 caractères qui ne sont pas enregistrés comme kanji, sélectionnez 1, 4 ou 8 caractères.
  • Compte tenu du nombre approprié de groupes, j'ai choisi 5 caractères à la fin car 5 groupes semblaient être bons.
  • Les kanji représentatifs sont les suivants, mais plus que de décider du représentant
  • Il est également intéressant que ** kanji de formes similaires soient placés à proximité ** sur le plan XY avec 3000 dimensions compressées.
  • Il était intéressant de pouvoir créer des ** groupes par tête ** avec un clustering basé sur la distance.
  • Le nombre de grappes a également été jugé à 5 groupes sur la base des résultats de la méthode du coude, de la méthode de la silhouette et du dendogramme.
  • Il était également intéressant de noter que les ** résultats de la visualisation en cluster de 5 clusters étaient raisonnablement bons **

Liste de vérification

No Comment choisir Représentant Saito
1 À partir de 4 kanji reconnus
1 caractèreSi vous choisissez, le représentant est
13.jpg
2 De tous les 33 kanji
1 caractèreSi tu choisis
28.jpg
3 De tous les 33 kanji
4 caractèresSi tu choisis
25.jpg26.jpg29.jpg08.jpg
4 De tous les 33 kanji
8 caractèresSi tu choisis
21.jpg26.jpg29.jpg31.jpg07.jpg12.jpg15.jpg19.jpg
5 Tous les 33 kanji
Combien de clustersDoit être divisé en
Environ 5 clustersCela semble bon
6 De tous les 33 kanji
5 caractèresSi tu choisis
08.jpg15.jpg23.jpg27.jpg29.jpg

finalement

  • Merci d'avoir traité une histoire aussi stupide.
  • Si vous le souhaitez, je vous serais reconnaissant si vous pouviez le partager.

Informations de référence

  • À propos de l'UMAP
    • https://umap-learn.readthedocs.io/en/latest/index.html
  • Discussion sur le clustering dans UMAP (semble être)
    • https://umap-learn.readthedocs.io/en/latest/index.html
  • À propos de KMeans
    • https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html
  • Examen du nombre de grappes (Yellow Brick)
    • https://www.scikit-yb.org/en/latest/api/cluster/elbow.html
    • https://www.scikit-yb.org/en/latest/api/cluster/silhouette.html
  • Dessin de dendogramme
    • https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.cluster.hierarchy.dendrogram.html

Fonction de visualisation

  • J'ai fait référence à cet article. Merci beaucoup. Je vais lier.
%matplotlib inline
%config InlineBackend.figure_format = 'retina'

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
from matplotlib import offsetbox
from sklearn.preprocessing import MinMaxScaler
from PIL import Image
import matplotlib.patches as patches

rc = {
  'font.family': ['sans-serif'],
  'font.sans-serif': ['Open Sans', 'Arial Unicode MS'],
  'font.size': 12,
  'figure.figsize': (8, 6),
  'grid.linewidth': 0.5,
  'legend.fontsize': 10,
  'legend.frameon': True,
  'legend.framealpha': 0.6,
  'legend.handletextpad': 0.2,
  'lines.linewidth': 1,
  'axes.facecolor': '#fafafa',
  'axes.labelsize': 10,
  'axes.titlesize': 14,
  'axes.linewidth': 0.5,
  'xtick.labelsize': 10,
  'xtick.minor.visible': True,
  'ytick.labelsize': 10,
  'figure.titlesize': 14
}
sns.set('notebook', 'whitegrid', rc=rc)

def colorize(d, color, alpha=1.0):
  rgb = np.dstack((d,d,d)) * color
  return np.dstack((rgb, d * alpha)).astype(np.uint8)

colors = sns.color_palette('tab10')

def showScatter(
    embeddings,
    clusterlabels,
    centers = [],
    imgs = all.T.reshape(-1,h,w),
):
    fig, ax = plt.subplots(figsize=(15,15))
    
    #Mise à l'échelle avant de dessiner un diagramme de dispersion
    scaler = MinMaxScaler()
    embeddings = scaler.fit_transform(embeddings)
    
    source = zip(embeddings, imgs ,clusterlabels)
    
    #Dessinez des kanji sur un diagramme de dispersion
    cnt = 0
    for pos, d , i in source:
        cnt = cnt + 1
        img = colorize(d, colors[i], 0.5)
        ab = offsetbox.AnnotationBbox(offsetbox.OffsetImage(img),0.03 + pos * 0.94,frameon=False)
        ax.add_artist(ab)
          
    #Dessinez des cercles concentriques à partir du centre de gravité
    if len(centers) != 0:
        for c in scaler.transform(centers):
            for r in np.arange(3,0,-1)*0.05:
                circle = patches.Circle(
                    xy=(c[0], c[1]),
                    radius=r,
                    fc='#FFFFFF', 
                    ec='black'
                )
                circle.set_alpha(0.3)
                ax.add_patch(circle)

            ax.scatter(c[0],c[1],s=300,marker="X")
  

    #Plage de dessin de l'axe
    limit = [-0.1,1.1]
    plt.xlim(limit)
    plt.ylim(limit)
    plt.show()

Recommended Posts