Dernière fois a utilisé la méthode train_supervised de fastText pour l'apprentissage supervisé et le regroupement des données d'articles de Yahoo News. Cette fois, utilisons la méthode train_unsupervised de fastText pour effectuer un apprentissage non supervisé et analyser si elle peut être regroupée aussi bien que la dernière fois.
① Charger la bibliothèque (2) Créez un fichier appelé utility.py pour stocker les fonctions créées jusqu'à présent. À partir de là, chargez les fonctions dont vous avez besoin cette fois. ③ Utilisez la fonction YN pour obtenir des articles Yahoo News. Vous pouvez obtenir environ 500 articles sur environ 10. Cette fonction est introduite sur ici.
# ①
import pandas as pd, numpy as np
from sklearn.model_selection import train_test_split
import fasttext
from sklearn import preprocessing
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import japanize_matplotlib
import re
# ②
import utility as util
wakati = util.wakati
M2A = util.MecabMorphologicalAnalysis
YN = util.YahooNews
cos_sim = util.cos_sim
# ③
df = YN(1000)
# df = pd.read_csv('./YahooNews.csv') #Si vous avez déjà acquis les données, lisez-les et lancez l'analyse!
df
[====================] 502 articles
title | category | text | |
---|---|---|---|
0 | Transféré dans une société holding à Pana 22 td> | Économie td> | Bloomberg Panasonic a annoncé le 13 qu'il passerait à une structure de société holding à partir d'avril 2022 ... td> |
1 | Plus de 1700 personnes infectées dans tout le pays, le nombre le plus élevé jamais enregistré td> | Domestique td> | Nippon News Network NNN La nouvelle personne infectée par le nouveau virus corona le 13e jour est N ... td> |
2 | Respect du mariage de Mako pour Leurs Majestés td> | Domestique td> | Le bureau de Miyauchi sera avec Mako Akishino, la fille aînée de M. et Mme Akishino, et Kei Komuro, un camarade de classe de l'ère ICU de l'Université chrétienne internationale, 29 ... td> |
3 | Les conseils de M. Trump sont partagés td> | International td> | Le président de CNN, Trump, qui est sûr d'être vaincu à l'élection présidentielle américaine, est celui qui a le plus confiance en lui alors qu'il élabore la stratégie du prochain mouvement ... |
4 | Ministre des affaires étrangères "Je veux étendre GoTo" td> | Domestique td> | CopyrightC Japan News Network All rights reser... |
... | ... | ... | ... |
497 | M. Byden au discours télévisé pour le public td> | International td> | Actualités AFP Le candidat à la présidence du Parti démocrate américain Joe Biden est dans la nuit du 6 et le matin du 7, heure du Japon ... td> |
498 | Alertes aux affrontements et aux émeutes aux États-Unis td> | International td> | All Nippon NewsNetworkANN Le vainqueur de l'élection présidentielle est incertain aux États-Unis ... td> |
499 | A accepté de reprendre le trafic commercial entre le Japon et la Chine td> | Domestique td> | Le trafic des hommes d'affaires, que les gouvernements japonais et chinois ont limité pour contrer le nouveau virus corona, reprendra au milieu de ce mois ... td> |
500 | Recomptage de l'élection présidentielle en Géorgie td> | International td> | Actualité AFP Le démocrate Joe Biden à l'élection présidentielle américaine est le républicain Donald Tran ... td> |
501 | Le président du CIO, Bach, viendra au Japon le 15 td> | Sports td> | Thomas Bach du Comité International Olympique CIO sur les Jeux Paralympiques de Tokyo reportés à l'été prochain ... td> |
502 rows × 3 columns
Je ne l'ai pas mentionné la dernière fois, mais cette fois, je vais considérer le sous-mot, qui est une caractéristique majeure de fastText.
Un sous-mot consiste à diviser un mot en «sous-mots» plus petits pour saisir la pertinence des mots.
Par exemple, vous pouvez apprendre la pertinence de mots qui ont une partie commune telle que «Go» et «Going».
L'application d'un sous-mot a amélioré la précision, je vais donc l'utiliser. Au contraire, il semble qu'il y ait un effet néfaste sur la langue katata.
Il peut être implémenté en passant maxn
et minn
aux arguments de train_supervised et train_unsupervised.
Les valeurs par défaut sont différentes pour train_supervised et train_unsupervised. Pour plus d'informations, accédez à GitHub.
Tout d'abord, à titre de comparaison, exécutez le contenu de Dernière fois à la fois.
#Stocker la catégorie et le corps dans la liste respectivement
cat_lst = ['__label__' + cat for cat in df.category]
text_lst = [M2A(text, mecab=wakati) for text in df.text]
#Divisé en train et valide
text_train, text_valid, cat_train, cat_valid = train_test_split(
text_lst, cat_lst, test_size=0.2, random_state=0, stratify=cat_lst
)
#Créer un train et des fichiers valides
with open('./s_train', mode='w') as f:
for i in range(len(text_train)):
f.write(cat_train[i] + ' '+ text_train[i])
with open('./s_valid', mode='w') as f:
for i in range(len(text_valid)):
f.write(cat_valid[i] + ' ' + text_valid[i])
#Apprentissage de modèle
model = fasttext.train_supervised(input='./s_train', lr=0.5, epoch=500, minn=3, maxn=5,
wordNgrams=3, loss='ova', dim=300, bucket=200000)
#Vérifiez la précision du modèle
# print("TrainData:", model.test('./s_news_train'))
print("ValidData:", model.test('./s_valid'))
#Préparation d'un graphique bidimensionnel à l'aide de données valides
with open("./s_valid") as f:
l_strip = [s.strip() for s in f.readlines()] # strip()Supprimer les caractères de saut de ligne à l'aide de
labels = []
texts = []
sizes = []
for t in l_strip:
labels.append(re.findall('__label__(.*?) ', t)[0])
texts.append(re.findall(' (.*)', t)[0])
sizes.append(model.predict(re.findall(' (.*)', t))[1][0][0])
#Génération de vecteur à partir d'un corps d'article valide
vectors = []
for t in texts:
vectors.append(model.get_sentence_vector(t))
#Convertir en numpy
vectors = np.array(vectors)
labels = np.array(labels)
sizes = np.array(sizes)
#Standardisation
ss = preprocessing.StandardScaler()
vectors_std = ss.fit_transform(vectors)
#Réduction de dimension
pca = PCA()
pca.fit(vectors_std)
feature = pca.transform(vectors_std)
feature = feature[:, :2]
#terrain
x0, y0, z0 = feature[labels=='Divertissement', 0], feature[labels=='Divertissement', 1], sizes[labels=='Divertissement']*1000
x1, y1, z1 = feature[labels=='Des sports', 0], feature[labels=='Des sports', 1], sizes[labels=='Des sports']*1000
x2, y2, z2 = feature[labels=='la vie', 0], feature[labels=='la vie', 1], sizes[labels=='la vie']*1000
x3, y3, z3 = feature[labels=='National', 0], feature[labels=='National', 1], sizes[labels=='National']*1000
x4, y4, z4 = feature[labels=='international', 0], feature[labels=='international', 1], sizes[labels=='international']*1000
x5, y5, z5 = feature[labels=='surface', 0], feature[labels=='surface', 1], sizes[labels=='surface']*1000
x6, y6, z6 = feature[labels=='Économie', 0], feature[labels=='Économie', 1], sizes[labels=='Économie']*1000
plt.figure(figsize=(14, 10))
plt.rcParams["font.size"]=20
plt.scatter(x0, y0, label="Divertissement", s=z0)
plt.scatter(x1, y1, label="Des sports", s=z1)
plt.scatter(x2, y2, label="la vie", s=z2)
plt.scatter(x3, y3, label="National", s=z3)
plt.scatter(x4, y4, label="international", s=z4)
plt.scatter(x5, y5, label="surface", s=z5)
plt.scatter(x6, y6, label="Économie", s=z6)
plt.title("Yahoo Actualités")
plt.xlabel('1st dimension')
plt.ylabel('2nd dimension')
plt.legend(title="category")
plt.show()
ValidData: (101, 0.801980198019802, 0.801980198019802)
Aucune étiquette n'est requise pour l'apprentissage non supervisé, il vous suffit donc d'écrire les données pour l'apprentissage. (1) La catégorie est stockée dans cat_lst, et les phrases sont séparées par la fonction M2A et stockées dans text_lst. (2) Divisez en données de train et données valides. ③ Enregistrez le texte dans un fichier.
# ①
cat_lst = [cat for cat in df.category]
text_lst = [M2A(text, mecab=wakati) for text in df.text]
# ②
text_train, text_valid, cat_train, cat_valid = train_test_split(
text_lst, cat_lst, test_size=0.2, random_state=0, stratify=cat_lst
)
# ③
with open('./u_train', mode='w') as f:
for i in range(len(text_train)):
f.write(text_train[i])
with open('./u_valid', mode='w') as f:
for i in range(len(text_valid)):
f.write(text_valid[i])
L'apprentissage non supervisé utilise train_unsupervised
.
model = fasttext.train_unsupervised('./u_train', epoch=500, lr=0.01, minn=3, maxn=5, dim=300)
Utilisez le modèle entraîné pour calculer la similitude du contenu de l'article.
① Utilisez la méthode get_sentence_vector
pour générer un vecteur de phrase à partir du modèle entraîné.
② Affichez la catégorie d'article et le texte.
(3) Calculez la similitude cosinus en utilisant la fonction cos_sim
lue ci-dessus.
# ①
vectors = []
for t in text_train:
vectors.append(model.get_sentence_vector(t.strip()))
# ②
print("<{}>".format(cat_train[0]))
print(text_train[0][:200], end="\n\n")
print("<{}>".format(cat_train[1]))
print(text_train[1][:200], end="\n\n")
print("<{}>".format(cat_train[2]))
print(text_train[2][:200], end="\n\n")
# ③
print("<{}><{}>".format(cat_train[0], cat_train[1]), cos_sim(vectors[0], vectors[1]))
print("<{}><{}>".format(cat_train[1], cat_train[2]), cos_sim(vectors[1], vectors[2]))
print("<{}><{}>".format(cat_train[0], cat_train[2]), cos_sim(vectors[0], vectors[2]))
Tracons enfin en deux dimensions.
① Convertir respectivement le vecteur et l'étiquette en tableau numpy
② Standardiser le vecteur
③ Réduction dimensionnelle du vecteur à l'aide de l'ACP
④ Tracez avec matplotlib. Contrairement à train_supervised
, vous ne pouvez pas obtenir la probabilité de la prédiction, donc tous les graphiques ont la même taille.
# ①
vectors = np.array(vectors)
labels = np.array(cat_train)
# ②
ss = preprocessing.StandardScaler()
vectors_std = ss.fit_transform(vectors)
# ③
pca = PCA()
pca.fit(vectors_std)
feature = pca.transform(vectors_std)
feature = feature[:, :2]
# ④
x0, y0 = feature[labels=='Divertissement', 0], feature[labels=='Divertissement', 1]
x1, y1 = feature[labels=='Des sports', 0], feature[labels=='Des sports', 1]
x2, y2 = feature[labels=='la vie', 0], feature[labels=='la vie', 1]
x3, y3 = feature[labels=='National', 0], feature[labels=='National', 1]
x4, y4 = feature[labels=='international', 0], feature[labels=='international', 1]
x5, y5 = feature[labels=='surface', 0], feature[labels=='surface', 1]
x6, y6 = feature[labels=='Économie', 0], feature[labels=='Économie', 1]
plt.figure(figsize=(14, 10))
plt.rcParams["font.size"]=20
plt.scatter(x0, y0, label="Divertissement", s=300)
plt.scatter(x1, y1, label="Des sports", s=300)
plt.scatter(x2, y2, label="la vie", s=300)
plt.scatter(x3, y3, label="National", s=300)
plt.scatter(x4, y4, label="international", s=300)
plt.scatter(x5, y5, label="surface", s=300)
plt.scatter(x6, y6, label="Économie", s=300)
plt.title("Yahoo Actualités")
plt.xlabel('1st dimension')
plt.ylabel('2nd dimension')
plt.legend(title="category")
plt.show()
Ensuite, regroupons les données valides. Le contenu est le même que celui de l'analyse des données de train, donc l'explication est omise.
vectors = []
for t in text_valid:
vectors.append(model.get_sentence_vector(t.strip()))
print("<{}>".format(cat_valid[0]))
print(text_valid[0][:200], end="\n\n")
print("<{}>".format(cat_valid[1]))
print(text_valid[1][:200], end="\n\n")
print("<{}>".format(cat_valid[2]))
print(text_valid[2][:200], end="\n\n")
print("<{}><{}>".format(cat_valid[0], cat_valid[1]), cos_sim(vectors[0], vectors[1]))
print("<{}><{}>".format(cat_valid[1], cat_valid[2]), cos_sim(vectors[1], vectors[2]))
print("<{}><{}>".format(cat_valid[0], cat_valid[2]), cos_sim(vectors[0], vectors[2]))
<Région> Le 9 novembre, il a été constaté que le nombre de personnes infectées par le nouveau virus corona à Hokkaido devait dépasser 200, le nombre le plus élevé jamais enregistré.Plus de 100 personnes pour le cinquième jour consécutif devraient enfin atteindre le niveau de 200 et la propagation de l'infection est attendue. Il semble qu'un nouveau cluster ait été confirmé: à Hokkaido, 119 personnes infectées ont été confirmées le 5.
vectors = np.array(vectors)
labels = np.array(cat_valid)
ss = preprocessing.StandardScaler()
vectors_std = ss.fit_transform(vectors)
pca = PCA()
pca.fit(vectors_std)
feature = pca.transform(vectors_std)
feature = feature[:, :2]
x0, y0 = feature[labels=='Divertissement', 0], feature[labels=='Divertissement', 1]
x1, y1 = feature[labels=='Des sports', 0], feature[labels=='Des sports', 1]
x2, y2 = feature[labels=='la vie', 0], feature[labels=='la vie', 1]
x3, y3 = feature[labels=='National', 0], feature[labels=='National', 1]
x4, y4 = feature[labels=='international', 0], feature[labels=='international', 1]
x5, y5 = feature[labels=='surface', 0], feature[labels=='surface', 1]
x6, y6 = feature[labels=='Économie', 0], feature[labels=='Économie', 1]
plt.figure(figsize=(14, 10))
plt.rcParams["font.size"]=20
plt.scatter(x0, y0, label="Divertissement", s=300)
plt.scatter(x1, y1, label="Des sports", s=300)
plt.scatter(x2, y2, label="la vie", s=300)
plt.scatter(x3, y3, label="National", s=300)
plt.scatter(x4, y4, label="international", s=300)
plt.scatter(x5, y5, label="surface", s=300)
plt.scatter(x6, y6, label="Économie", s=300)
plt.title("Yahoo Actualités")
plt.xlabel('1st dimension')
plt.ylabel('2nd dimension')
plt.legend(title="category")
plt.show()
―― En adoptant le sous-mot, la précision a été encore améliorée depuis le moment de l'article précédent. 0,75 → 0,80 ――Semblable à la dernière fois, il existe de nombreuses parties qui se chevauchent entre le «divertissement» et le «sport» dans la première dimension, mais elles sont clairement séparées dans la seconde dimension. Je suis convaincu que «divertissement» et «sport» sont proches l'un de l'autre. ―― «International» et «domestique» sont bien séparés et il existe une «économie» entre eux. Comme pour la dernière fois, c'est également convaincant. ――Dans l'article précédent, la "région" n'était pas claire, mais cette fois les caractéristiques sont fortes dans le sens bidimensionnel. «Dans l'ensemble, il se sent plus clairement classé que la dernière fois.
――Il y a peu de parties qui se chevauchent et il a été soigneusement classé dans son ensemble. DomesticIl y a «domestique» au centre, «international» à gauche et «économie» au centre. C'est assez différent qu'avant. «Bien que« sports »et« divertissements »soient assez proches cette fois-ci, les« sports »étaient répartis sur une large gamme. ―― La «région» est divisée en deux. Cette tendance peut être vue même par les apprenants supervisés, il peut donc y avoir certains critères.
Cette fois, je l'ai analysé en apprenant sans professeur, mais j'ai été surpris que le classement soit réussi. Puisqu'il n'y a pas d'étiquette, cela signifie que vous pouvez obtenir "international" ou "sports" à partir du texte. Je suis très curieux de savoir quel type de fonctionnalités le modèle acquiert et reflète réellement dans la création de vecteurs. Je veux creuser plus profondément dans fastText! !! !!
Yahoo! News fastText Explication de l'installation et de l'utilisation de fastText publiée par Facebook Effets indésirables du sous-mot fastText fastText tutorial(Word representations) GitHub (fastText/python) fastText est incroyable! Clustering "Yahoo! News"