Dans cet article, nous allons implémenter et expliquer comment le clustering de maximisation de la quantité d'informations de l'apprentissage non supervisé est effectué pour les actualités liveoor à l'aide de la version japonaise de BERT dans Google Colaboratory.
--Contenu jusqu'à la vectorisation des phrases en utilisant la version japonaise de BERT dans Google Colaboratory,
J'ai expliqué à ce sujet dans les articles publiés jusqu'à présent, alors veuillez d'abord jeter un œil ici.
** Liste des séries ** [1] [Explication de la mise en œuvre] Comment utiliser la version japonaise de BERT dans Google Colaboratory (PyTorch) [2] [Explication de la mise en œuvre] Classification des actualités Livedoor dans la version japonaise BERT: Google Colaboratory (PyTorch) [3] [Explication de la mise en œuvre] Science du cerveau et apprentissage non supervisé. Classer MNIST par clustering de maximisation de la quantité d'informations [4] * Cet article [Explication de l'implémentation] Classifier les actualités de livingoor par apprentissage japonais BERT x non supervisé (regroupement de maximisation de la quantité d'informations)
La dernière fois, j'ai écrit un article sur l'image numérique manuscrite du MNIST. Invariant Information Clustering for Unsupervised Image Classification and Segmentation
Regroupement de l'apprentissage non supervisé à l'aide d'informations mutuelles IIC(Invariant Information Clustering) A été effectuée.
Cette fois, nous montrerons ce qui se passe lorsque chaque article de news de livingoor news est vectorisé avec le japonais BERT et qu'il est appris sans supervision (clustering) avec IIC.
Dans le cas de MNIST, le résultat de la classification est divisé en fonction de l'étiquette numérique de l'apprentissage supervisé, et il est bon qu'il puisse être utilisé pour un apprentissage supervisé, mais qu'en est-il des données textuelles?
J'essaierai ceci.
Le flux de cette implémentation est
Ce sera.
Le code d'implémentation de cet article se trouve dans le référentiel GitHub ci-dessous.
GitHub: Comment utiliser la version japonaise de BERT dans Google Colaboratory: code de mise en œuvre Il s'agit de 4_BERT_livedoor_news_IIC_on_Google_Colaboratory.ipynb.
Le contenu jusqu'à présent est [[2] [Explication de la mise en œuvre] Classification des actualités Livedoor en version japonaise BERT: Google Colaboratory (PyTorch)](https: //)
En l'état, je vais omettre la publication dans cet article.
Enfin, créez un DataLoader d'entraînement, de validation et de test en procédant comme suit:
#Créer un DataLoader (simplement appelé iterater dans le contexte de torchtext)
batch_size = 16 #BERT utilise environ 16 et 32
dl_train = torchtext.data.Iterator(
dataset_train, batch_size=batch_size, train=True)
dl_eval = torchtext.data.Iterator(
dataset_eval, batch_size=batch_size, train=False, sort=False)
dl_test = torchtext.data.Iterator(
dataset_test, batch_size=batch_size, train=False, sort=False)
#Assembler dans un objet dictionnaire
dataloaders_dict = {"train": dl_train, "val": dl_eval}
Vectorisez le corps de l'article de liveoor news avec la version japonaise de BERT
Ce sera une vectorisation du document.
Cette fois, je traiterai simplement le vecteur incorporé de 768 dimensions du premier mot de BERT ([CLS]) comme un vecteur de document (il existe différentes manières de créer un vecteur de document et sa validité).
Comme c'est une perte de temps de vectoriser les données d'un document à chaque fois lors de la formation d'un réseau neuronal pour le clustering par IIC, créez un DataLoader qui a été converti en vecteur de document par BERT.
La mise en œuvre est la suivante:
Tout d'abord, préparez le corps principal de BERT. Il s'agit d'une version paramétrée de l'Université de Tohoku qui a déjà appris le japonais.
from transformers.modeling_bert import BertModel
#Modèle de paramètre appris japonais de BERT
model = BertModel.from_pretrained('bert-base-japanese-whole-word-masking')
model.eval()
print('Configuration réseau terminée')
Ensuite, définissez une fonction à vectoriser avec BERT.
#Définir une fonction à vectoriser avec BERT
def vectorize_with_bert(net, dataloader):
#Vérifiez si le GPU peut être utilisé
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("Appareil utilisé:", device)
print('-----start-------')
#Réseau vers GPU
net.to(device)
#Si le réseau est réparé dans une certaine mesure, accélérez-le
torch.backends.cudnn.benchmark = True
#Mini taille de lot
batch_size = dataloader.batch_size
#Boucle pour récupérer un mini-lot à partir du chargeur de données
for index, batch in enumerate(dataloader):
#batch est un objet dictionnaire Text and Lable
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
inputs = batch.Text[0].to(device) #Phrase
labels = batch.Label.to(device) #étiquette
#Calcul à terme
with torch.set_grad_enabled(False):
#Entrez dans Ber
result = net(inputs)
# sequence_Extraire le premier mot vecteur de sortie
vec_0 = result[0] #Le premier 0 est la séquence_Afficher la sortie
vec_0 = vec_0[:, 0, :] #Tous les lots. Tous les 768 éléments du premier 0ème mot
vec_0 = vec_0.view(-1, 768) #Taille[batch_size, hidden_size]Conversion en
#Organisez les données vectorisées dans une liste de torches
if index == 0:
list_text = vec_0
list_label = labels
else:
list_text = torch.cat([list_text, vec_0], dim=0)
list_label = torch.cat([list_label, labels], dim=0)
return list_text, list_label
Vectorisez les DataLoaders de formation, de validation et de test avec les fonctions définies.
#Convertir DataLoader en version vectorisée
#Cela prend un peu moins de 5 minutes
list_text_train, list_label_train = vectorize_with_bert(model, dl_train)
list_text_eval, list_label_eval = vectorize_with_bert(model, dl_eval)
list_text_test, list_label_test = vectorize_with_bert(model, dl_test)
Faites ensuite de cette liste un ensemble de données PyToch.
#Convertir la liste des torches en jeu de données
from torch.utils.data import TensorDataset
dataset_bert_train = TensorDataset(
list_label_train.view(-1, 1), list_text_train)
dataset_bert_eval = TensorDataset(list_label_eval.view(-1, 1), list_text_eval)
dataset_bert_test = TensorDataset(list_label_test.view(-1, 1), list_text_test)
Enfin, définissez l'ensemble de données sur DataLoader. Ce DataLoader est utilisé pour l'apprentissage du réseau IIC (Invariant Information Clustering).
#Faites-en un chargeur de données
from torch.utils.data import DataLoader
batch_size = 1024
dl_bert_train = DataLoader(
dataset_bert_train, batch_size=batch_size, shuffle=True, drop_last=True)
# drop_le dernier est le dernier lot de mini-lots_Ignorer si la taille ne suffit pas
dl_bert_eval = DataLoader(
dataset_bert_eval, batch_size=batch_size, shuffle=False)
dl_bert_test = DataLoader(
dataset_bert_test, batch_size=batch_size, shuffle=False)
Avec ce qui précède, le texte des news de livingoor a été vectorisé en japonais BERT.
Il ne vous reste plus qu'à regrouper ces données vectorisées.
Ensuite, préparez un modèle d'apprentissage en profondeur d'IIC. Cette partie est essentiellement
Il a la même configuration que.
Le modèle de réseau neuronal doit correspondre à un vecteur de 768 dimensions. Cette fois, le montant de la caractéristique est converti en répétant le pliage de 1d.
Le clustering 10 fois le nombre de clusterings réellement estimé par overclustering est également effectué en même temps, et le réseau qui capture des fonctionnalités infimes est formé.
import torch.nn as nn
import torch.nn.functional as F
OVER_CLUSTRING_RATE = 10
class NetIIC(nn.Module):
def __init__(self):
super(NetIIC, self).__init__()
# multi-la tête ne fait pas cette fois
self.conv1 = nn.Conv1d(1, 400, kernel_size=768, stride=1, padding=0)
self.bn1 = nn.BatchNorm1d(400)
self.conv2 = nn.Conv1d(1, 300, kernel_size=400, stride=1, padding=0)
self.bn2 = nn.BatchNorm1d(300)
self.conv3 = nn.Conv1d(1, 300, kernel_size=300, stride=1, padding=0)
self.bn3 = nn.BatchNorm1d(300)
self.fc1 = nn.Linear(300, 250)
self.bnfc1 = nn.BatchNorm1d(250)
#Correspond-il à 9 catégories d'actualités liveoor? 9 catégories à attendre
self.fc2 = nn.Linear(250, 9)
# overclustering
#En regroupant plus que l'hypothèse réelle, il sera possible de capturer des changements infimes dans le réseau.
self.fc2_overclustering = nn.Linear(250, 9*OVER_CLUSTRING_RATE)
def forward(self, x):
x = x.view(x.size(0), 1, -1)
x = F.relu(self.bn1(self.conv1(x)))
x = x.view(x.size(0), 1, -1)
x = F.relu(self.bn2(self.conv2(x)))
x = x.view(x.size(0), 1, -1)
x = F.relu(self.bn3(self.conv3(x)))
x = x.view(x.size(0), -1)
x_prefinal = F.relu(self.bnfc1(self.fc1(x)))
# multi-N'utilisez pas la tête
y = F.softmax(self.fc2(x_prefinal), dim=1)
y_overclustering = F.softmax(self.fc2_overclustering(
x_prefinal), dim=1) # overclustering
return y, y_overclustering
Définit une fonction d'initialisation pour les paramètres de pondération du modèle.
import torch.nn.init as init
def weight_init(m):
"""Initialisation du poids"""
if isinstance(m, nn.Conv1d):
init.normal_(m.weight.data)
if m.bias is not None:
init.normal_(m.bias.data)
elif isinstance(m, nn.BatchNorm1d):
init.normal_(m.weight.data, mean=1, std=0.02)
init.constant_(m.bias.data, 0)
elif isinstance(m, nn.Linear):
# Xavier
# init.xavier_normal_(m.weight.data)
# He
init.kaiming_normal_(m.weight.data)
if m.bias is not None:
init.normal_(m.bias.data)
Définit comment calculer la fonction de perte pour IID.
Calculez la quantité d'informations mutuelles entre la sortie (x_out) lorsque les données vectorisées cible sont entrées dans NetIID et la sortie (x_tf_out) lorsque les données converties des données vectorisées cible sont entrées dans NetIID.
Voir l'article précédent pour plus de détails sur l'implémentation ici.
#Définition de la fonction de perte par IIS
#Référence: https://github.com/RuABraun/phone-clustering/blob/master/mnist_basic.py
import sys
def compute_joint(x_out, x_tf_out):
bn, k = x_out.size()
assert (x_tf_out.size(0) == bn and x_tf_out.size(1) == k), '{} {} {} {}'.format(
bn, k, x_tf_out.size(0), x_tf_out.size(1))
p_i_j = x_out.unsqueeze(2) * x_tf_out.unsqueeze(1) # bn, k, k
p_i_j = p_i_j.sum(dim=0) # k, k
p_i_j = (p_i_j + p_i_j.t()) / 2. # symmetrise
p_i_j = p_i_j / p_i_j.sum() # normalise
return p_i_j
def IID_loss(x_out, x_tf_out, EPS=sys.float_info.epsilon):
# has had softmax applied
bs, k = x_out.size()
p_i_j = compute_joint(x_out, x_tf_out)
assert (p_i_j.size() == (k, k))
p_i = p_i_j.sum(dim=1).view(k, 1).expand(k, k)
p_j = p_i_j.sum(dim=0).view(1, k).expand(k, k)
# avoid NaN losses. Effect will get cancelled out by p_i_j tiny anyway
#Ceci est la version 1 de PyTorch.S'il est 3 ou plus, une erreur se produira.
# https://discuss.pytorch.org/t/pytorch-1-3-showing-an-error-perhaps-for-loss-computed-from-paired-outputs/68790/3
#p_i_j[(p_i_j < EPS).data] = EPS
#p_j[(p_j < EPS).data] = EPS
#p_i[(p_i < EPS).data] = EPS
p_i_j = torch.where(p_i_j < EPS, torch.tensor(
[EPS], device=p_i_j.device), p_i_j)
p_j = torch.where(p_j < EPS, torch.tensor([EPS], device=p_j.device), p_j)
p_i = torch.where(p_i < EPS, torch.tensor([EPS], device=p_i.device), p_i)
# https://qiita.com/Amanokawa/items/0aa24bc396dd88fb7d2a
#Ajout du poids alpha pour référence
alpha = 2.0
loss = (- p_i_j * (torch.log(p_i_j) - alpha *
torch.log(p_j) - alpha*torch.log(p_i))).sum()
return loss
Ensuite, définissez la transformation à appliquer aux données vectorisées d'intérêt.
Cette fonction de conversion est la clé de l'IIC.
Dans le cas de données d'image, la conversion affine (rotation / étirement), le changement de rapport d'aspect, l'écrêtage (écrêtage) et l'ajout de bruit sont effectués selon l'augmentation normale des données.
Que dois-je faire avec les données textuelles ...
Lors de l'augmentation des données dans les compétitions telles que Kaggle, nous les traduisons une fois dans une autre langue.
Cette fois, je vais simplement ajouter du bruit en fonction de l'écart type de toutes les données vectorielles.
#Définition d'une fonction qui ajoute du bruit aux données
device = 'cuda' if torch.cuda.is_available() else 'cpu'
tensor_std = list_text_train.std(dim=0).to(device)
def perturb_data(x):
y = x.clone()
noise = torch.randn(len(tensor_std)).to(device)*tensor_std*2.0
noise = noise.expand(x.shape[0], -1)
y += noise
return y
Maintenant que les modèles DataLoader et IIC sont prêts, formons les poids du modèle IIC.
Tout d'abord, définissez la fonction de formation.
#Définition de la fonction d'apprentissage
def train(total_epoch, model, train_loader, optimizer, device):
#Mettre le réseau en mode formation
model.train()
#Programmateur de taux d'apprentissage CosAnnealing
scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(
optimizer, T_0=2, T_mult=2, eta_min=0)
for epoch in range(total_epoch):
for batch_idx, (target, data) in enumerate(train_loader):
#Changement du taux d'apprentissage
scheduler.step()
data_perturb = perturb_data(data) #Donner du bruit et créer des données converties
#Envoyer si envoyé au GPU
data = data.to(device)
data_perturb = data_perturb.to(device)
#Initialisation de la fonction d'optimisation
optimizer.zero_grad()
#Entrez dans le réseau neuronal
output, output_overclustering = model(data)
output_perturb, output_perturb_overclustering = model(data_perturb)
#Calcul des pertes
loss1 = IID_loss(output, output_perturb)
loss2 = IID_loss(output_overclustering,
output_perturb_overclustering)
loss = loss1 + loss2
#Mis à jour pour réduire les pertes
loss.backward()
optimizer.step()
#Sortie de journal
if epoch % 50 == 0:
print('Train Epoch {} \tLoss1: {:.6f} \tLoss2: {:.6f} \tLoss_total: {:.6f}'.format(
epoch, loss1.item(), loss2.item(), loss1.item()+loss2.item()))
return model, optimizer
Dans la formation ci-dessus, le taux d'apprentissage est modifié en préparant les redémarrages à chaud du recuit cosinus du planificateur.
Il s'agit d'un appareil qui modifie le taux d'apprentissage comme indiqué ci-dessous pour faciliter l'apprentissage des paramètres de la solution locale à la solution minimale globale lorsque la valeur est soudainement augmentée à partir d'une petite valeur.
Figure: devis https://www.kaggle.com/c/imet-2019-fgvc6/discussion/94783
Nous effectuons des apprentissages. Cette fois, la taille du lot est de 1 024 et les données elles-mêmes sont d'environ 4 000, nous augmentons donc le nombre d'époques.
Il faut moins de 5 minutes pour apprendre.
#Mise en œuvre de l'apprentissage (moins de 5 minutes)
total_epoch = 1000
optimizer = torch.optim.Adam(net.parameters(), lr=5e-4) #Fonction d'optimisation
model_trained, optimizer = train(
total_epoch, net, dl_bert_train, optimizer, device)
Maintenant que la formation est terminée, déduisons avec les données de test. Pour faciliter la compréhension des résultats, préparez un DataLoader pour le test avec une taille de mini-lot 1 et inférez un par un. Stockez le résultat.
La fonction est définie ci-dessous.
#Vérifiez les résultats du cluster de classification du modèle
import numpy as np
#Préparer le chargeur de données pour un test de taille 1 en mini-lot
dl_bert_test = DataLoader(
dataset_bert_test, batch_size=1, shuffle=False)
def test(model, device, test_loader):
model.eval()
out_targs = []
ref_targs = []
#Préparer une liste pour la sortie
total_num = len(test_loader)
# index, (target_label, inferenced_label)
output_list = np.zeros((total_num, 2))
with torch.no_grad():
for batch_idx, (target, data) in enumerate(test_loader):
data = data.to(device)
target = target.to(device)
outputs, outputs_overclustering = model(data)
#Ajouter le résultat de la classification à la liste
out_targs.append(outputs.argmax(dim=1).cpu())
ref_targs.append(target.cpu())
#Mettez les résultats dans une liste
output_list[batch_idx, 0] = target.cpu() #Étiquette de réponse correcte
output_list[batch_idx, 1] = outputs.argmax(dim=1).cpu() #Étiquette de prédiction
out_targs = torch.cat(out_targs)
ref_targs = torch.cat(ref_targs)
return out_targs.view(-1, 1).numpy(), ref_targs.numpy(), output_list
Effectuer une inférence avec des données de test.
#Effectuer une inférence avec des données de test
out_targs, ref_targs, output_list = test(model_trained, device, dl_bert_test)
Vérifiez le tableau de fréquence de la matrice de confusion des résultats d'inférence dans les données de test.
#Faire une matrice de confusion
matrix = np.zeros((9, 9))
#Créez une classe de réponse correcte pour les actualités liveoor verticalement et une table de fréquences pour la classe jugée horizontalement
for i in range(len(out_targs)):
row = ref_targs[i]
col = out_targs[i]
matrix[row][col] += 1
np.set_printoptions(suppress=True)
print(matrix)
Le résultat de sortie est le suivant.
[[ 55. 0. 1. 0. 4. 47. 2. 76. 0.]
[ 3. 40. 4. 0. 14. 1. 1. 0. 116.]
[ 7. 39. 21. 4. 16. 3. 6. 3. 1.]
[ 11. 60. 16. 4. 13. 8. 27. 2. 17.]
[ 8. 6. 20. 107. 1. 8. 16. 0. 1.]
[ 11. 17. 15. 0. 40. 6. 78. 7. 0.]
[ 18. 3. 65. 40. 13. 15. 14. 3. 1.]
[ 63. 7. 45. 11. 2. 42. 7. 1. 1.]
[ 27. 0. 6. 0. 4. 61. 1. 61. 1.]]
De plus, l'axe vertical est dans l'ordre suivant après vérification du contenu de dic_id2cat
.
{0: 'sports-watch',
1: 'dokujo-tsushin',
2: 'livedoor-homme',
3: 'peachy',
4: 'smax',
5: 'movie-enter',
6: 'it-life-hack',
7: 'kaden-channel',
8: 'topic-news'}
Premièrement, les clusters qui étaient supposés être des classes, comme dans MNIST, ne correspondent pas parfaitement. Je pense que c'est quelque chose comme ça.
Si l'on vous demande de «classer un grand nombre de documents en plusieurs types», je pense que même les humains classeront (regrouperont) selon divers modèles. Lorsqu'on m'a demandé de classer les news de livingoor en 9 catégories, cette fois j'ai obtenu ce résultat.
Le deuxième cluster estimé est principalement "it-life-hack" et "kaden-channel". Le troisième des clusters estimés est «smax (smartphones et gadgets)». Le dernier cluster inféré semble être un cluster avec beaucoup de "communication unique".
L'avant-dernier est principalement "sports-watch" et "topic-news". Les classes "sports-watch" et "topic-news" sont dans le cluster estimé Il est séparé en 0e, 5e et 7e.
Le texte du 5ème cluster et le texte du 7ème cluster de "sports-watch" Le texte du 5ème cluster et le texte du 7ème cluster dans "topic-news"
Jetons un coup d'œil aux fonctionnalités du cluster 5 et du cluster 7.
#Vérifiez le résultat du cluster
#「sports-Texte du cinquième groupe de "montre", texte du septième groupe
#「topic-Texte du 5e groupe de "nouvelles", texte du 7e groupe
#Jetons un coup d'œil aux fonctionnalités du cluster 5 et du cluster 7.
import pandas as pd
df2 = pd.DataFrame(output_list)
df2.columns=["Classe de réponse correcte", "Cluster estimé"]
df2.head()
df2[(df2['Classe de réponse correcte']==0) & (df2['Cluster estimé']==5)].head()
La sortie est la suivante.
Classe correcte Cluster estimé
21 0.0 5.0
59 0.0 5.0
126 0.0 5.0
142 0.0 5.0
153 0.0 5.0
Jetons un coup d'œil aux 21e et 59e phrases de l'ensemble de données de test.
#Le document original est placé dans df. Regardez environ 300 caractères.
print(df.iloc[21, 0][:300])
print(df.iloc[59, 0][:300])
La première phrase du cinquième groupe de "montre de sport" est
Le 29 du mois dernier, après avoir pris sa retraite en tant que lutteur professionnel, Kotetsu Yamamoto, qui était aimé par les fans en tant que joueur entraîneur, commentateur et arbitre, est décédé subitement des suites d'une encéphalopathie hypoxique et a profondément attristé les fans et les parties liées. À ce moment-là, "Weekly Asahi Performing Arts" sorti le 7 de cette semaine rapportait une action incroyable qui montre "immédiatement avant sa mort" de M. Yamamoto dans le coin "NEWS SHOT!". L'ancien rédacteur hebdomadaire de lutte professionnelle Tarzan Yamamoto, qui a commenté le magazine, a déclaré: "Le corps, qui mesure 170 cm et pèse 113 kg, maintient toujours des muscles qui rappellent l'ère active. Il est aussi dur que les jeunes. Après l'entraînement, j'avais un appétit incroyable quand j'avais 68 ans, mais en fait, M. Yamamoto était diabétique », dit-il.
est devenu.
De même,
La première phrase du 7e groupe de «montre de sport» est
Entretien avec M. Hiromitsu Ochiai, ancien directeur des Dragons de Chunichi, où des mots choquants tels que «tout est devenu fou», «je n'ai jamais touché au lanceur», et «personne ne me fait confiance» sont apparus les uns après les autres. .. Sur Nippon Television "Going! Sports & News", le commentateur de baseball Taku Egawa était l'auditeur, et le modèle a été diffusé pendant deux nuits (17 et 18). Dans la première émission, M. Ochiai a révélé un épisode inconnu en disant: «Si je porte un uniforme l'année prochaine, je ne parlerai pas pour autant», mais la deuxième partie de l'émission est encore plus surprenante. C'est devenu le contenu qui devrait être. Voici un résumé de l'entrevue. Egawa: Pensiez-vous que vous pourriez être le meilleur au Japon cette année? Je ne pensais pas
est. La première phrase du cinquième groupe de "sujets-actualités" est
En Corée, c'est une règle générale que les moines sont célibataires, mais le Facebook du moine, qui dit: «J'étais désespéré et j'ai décidé de quitter la maison sans être populaire du sexe opposé», est devenu un sujet brûlant sur le babillard en ligne coréen. Le moine, nommé Hyobon, a déclaré sur Facebook le 19: "Je n'étais pas populaire auprès du sexe opposé dans la vingtaine ... J'ai fini par conclure que je ne pouvais rien y faire et j'ai décidé de quitter la maison. Tout le monde a abandonné. En y pensant maintenant, j'aurais dû faire des tours et des punks quand j'étais jeune », a-t-il déclaré à propos de son expérience de moine. Concernant la vie d'un prêtre, il a dit: "Plus vite vous quittez la maison, plus vite vous devenez grand. Si vous devenez grand, vous n'avez pas à vous soucier du riz et de la lessive."
est. La première phrase du 7e groupe de "sujets-actualités" est
Le 18, le Nihon Keizai Shimbun a rendu compte de la réalité déformée de la zone sinistrée dans un article intitulé «Une autre demande spéciale de reconstruction de situation anormale / Compensation nucléaire ... ing. Dans le même article, il a souligné que si la famille à indemniser est une famille de cinq personnes, 800000 yens par mois seront dans la poche, "j'ai reçu de l'argent de TEPCO, et même si je ne travaille pas, je peux pachinko, manger des sushis, et avoir un nouveau smartphone et un nouveau sac. Les mots de la population locale «Je le fais» sont affichés. L'indemnisation qui revient aux victimes et comment l'utiliser se positionne comme une «régénération déformée». Sur le babillard en ligne, "je n'ai pas récolté d'argent, je n'avais pas d'angle mort", "Sama-sama", "ça ne me dérange pas parce que les smartphones et les sushis sont consommés, mais le pachinko n'est pas bon."
est.
Vous ne pouvez pas vraiment comprendre les caractéristiques simplement en regardant le texte. .. ..
Cependant, vous pouvez voir que le sport et l'actualité ont des atmosphères d'articles très similaires.
Plus que cela, pour avoir une meilleure idée des caractéristiques des clusters IIC
De telles opérations peuvent être envisagées.
C'est trop long à faire dans cet article, c'est donc tout pour cette fois.
Le code d'implémentation de cet article se trouve dans le référentiel GitHub ci-dessous.
GitHub: Comment utiliser la version japonaise de BERT dans Google Colaboratory: code de mise en œuvre Il s'agit de 4_BERT_livedoor_news_IIC_on_Google_Colaboratory.ipynb.
Ce qui précède est un exemple d'implémentation et une explication pour les news de livingoor en tant que clustering IIC pour l'apprentissage non supervisé en japonais BERT.
Merci pour la lecture.
[Clause de non-responsabilité] Le contenu de cet article lui-même est l'opinion / la transmission de l'auteur, et non l'opinion officielle de la société à laquelle l'auteur appartient.
Recommended Posts