[PYTHON] J'ai essayé de visualiser les signets volant vers Slack avec Doc2Vec et PCA

Ceci est l'article sur le 11e jour du calendrier de l'Avent.

c'est

Une représentation distribuée des titres d'articles mis en signet par tous (4 personnes) acquis et visualisés

Quand je le signale, IFTTT le prend et le recrache pour le relâcher, donc je vais le traiter à partir de là

Conditions préalables

--Environnement

Références / utilisé

  1. [Réunion de changement d'emploi] Traitez le bouche-à-oreille en langage naturel avec word2vec pour classer les entreprises
  2. [word2vec] Visualisons le résultat du traitement en langage naturel des avis d'entreprises
  3. [Mémorandum de prétraitement japonais par python](https://datumstudio.jp/blog/python%E3%81%AB%E3%82%88%E3%82%8B%E6%97%A5%E6% 9C% AC% E8% AA% 9E% E5% 89% 8D% E5% 87% A6% E7% 90% 86% E5% 82% 99% E5% BF% 98% E9% 8C% B2)
  4. Sauvegarde facile du journal de discussion slack
  5. models.doc2vec(gensim)
  6. slack-dump
  7. slack api

Ce que tu peux faire

Prévoyez avant de faire

--R-kun

résultat

La portée et le chevauchement sont intuitivement proches des attentes

スクリーンショット 2019-12-11 19.16.44.png

Préparation

Comment faire en sorte que IFTTT publie des signets Hatena sur Slack

procédure

Je vais omettre les détails, mais le mécanisme lui-même est complété par le flux de la figure ci-dessous, mais il est nécessaire de saisir l'URL pour recevoir le flux RSS entre les 4ème et 5ème frames, cette fois c'est un signet Hatena, donc http: //b.hatena .ne.jp / <nom d'utilisateur> / rss

Comme ça

Raison

Dois-je aimer les utilisateurs de Hatena?

Ce n'est pas mal (plutôt, vous pouvez faire les deux), mais vous pouvez vous sentir libre de commenter comme ça dans la communauté.

IMG_52CF406E5EED-1.jpeg
Dois-je utiliser la commande / le flux Slack?

Vous pouvez personnaliser la publication afin de pouvoir l'utiliser pour le plaisir comme cette fois-ci, et l'utilisation de la commande Slack prend beaucoup de place, ce qui est un problème

Recevoir les messages postés de Slack

Ces deux types semblent faciles à faire

  1. API Slack
    • https://api.slack.com/methods/channels.history
  2. Go tool (cette fois)
    • https://github.com/joefitzgerald/slack-dump

Vous avez quand même besoin d'un jeton, alors procurez-vous-le depuis ici

$ wget https://github.com/PyYoshi/slack-dump/releases/download/v1.1.3/slack-dump-v1.1.3-linux-386.tar.gz
$ tar -zxvf slack-dump-v1.1.3-linux-386.tar.gz
$ linux-386/slack-dump -t=<token> <channel>

Prenez-le avec DM et déplacez-le vers un autre endroit car c'est un obstacle

python


import zipfile, os

os.mkdir('dumps')
with zipfile.ZipFile('./zipfile_name') as z:
    for n in z.namelist():
        if 'channel_name' in n:
            z.extract(n, './dumps')

Ouvrez le fichier et obtenez le contenu, car il est par date, faites-en un

python


import json, glob

posts = []
files = glob.glob('./dumps/channel/<channel_name>/*.json'.format(dirname))
for file in files:
    with open(file) as f:
        posts += json.loads(f.read())

Extraire le message et associer le titre de l'article au nom d'utilisateur (cette zone dépend des paramètres dans IFTTT)

python


user_post_dic = {
    'Y': [],
    'S': [],
    'M': [],
    'R': [],
}

for p in posts:
    if "username" not in p or p["username"] != "IFTTT":
        continue
    for a in p["attachments"]:
        #Évitement divers
        try:
            user_post_dic[a["text"]].append(a["title"])
        except:
            pass
        
users = user_post_dic.keys()
print([[u, len(user_post_dic[u])] for u in users])

production


[['Y', 864], ['S', 896], ['M', 240], ['R', 79]]

Histoire principale

Prétraitement

Nettoyage et écriture

Le message posté ressemble à ceci et le titre et l'URL du site ne sont pas nécessaires, supprimez-le

Utilisez Neodim dans la zone de texte de votre navigateur<http://Developers.IO|Developers.IO>

Mesures de sécurité pour les ingénieurs front-end/ #frontkansai 2019 - Speaker Deck

Japonais avec matplotlib

Réintroduction à JavaScript moderne/ Re-introduction to Modern JavaScript - Speaker Deck

Je ne savais pas comment utiliser re, alors je l'ai poussé. De plus, il écrit également dans MeCab, et bien que l'environnement comprenne sudapipy etc., il est rapide d'utiliser quelque chose qui est familier à la main.

python


import MeCab, re
m = MeCab.Tagger("-Owakati")

_tag = re.compile(r'<.*?>')
_url = re.compile(r'(http|https)://([-\w]+\.)+[-\w]+(/[-\w./?%&=]*)?')
_title = re.compile(r'( - ).*$')
_par = re.compile(r'\(.*?\)')
_sla = re.compile(r'/.*$')
_qt = re.compile(r'"')
_sep = re.compile(r'\|.*$')
_twi = re.compile(r'(.*)on Twitter: ')
_lab = re.compile(r'(.*) ⇒ \(')
_last_par = re.compile(r'\)$')

def clean_text(text):
    text = text.translate(str.maketrans({chr(0xFF01 + i): chr(0x21 + i) for i in range(94)}))
    text = re.sub(_lab, '', text)
    text = re.sub(_tag, '', text)
    text = re.sub(_url, '', text)
    text = re.sub(_title, '', text)
    text = re.sub(_sla,  '', text)
    text = re.sub(_qt,  '', text)
    text = re.sub(_sep, '', text)
    text = re.sub(_twi, '', text)
    text = re.sub(_par, '', text)
    text = re.sub(_last_par, '', text)
    return text

p_all = []
m_all = []
for u in users:
    user_post_dic[u] = list(map(clean_text, p_dic[u]))
    m_all += [m.parse(p).split('\n')[0] for p in p_dic[u]]
    p_all += [u + '**' + p for p in user_post_dic[u]]

Dans p_all, le nom d'utilisateur est ajouté au début de chaque élément car le texte disparaît à cause du prétraitement et de l'index des décalages de liste, il est donc lié de manière douloureuse. (À propos, si l'URL est utilisée comme titre de l'article, etc.)

Pour le moment c'est devenu beau

Utilisez Neodim dans la zone de texte de votre navigateur
 
Mesures de sécurité pour les ingénieurs front-end
 
Japonais avec matplotlib

Réintroduction à JavaScript moderne

Doc2Vec Le corps du texte qui est le matériau lorsque m_all acquiert l'expression distribuée p_all est juste un nom

Les paramètres ne sont pas considérés avec enthousiasme

python


from gensim import models

#Article de référence: http://qiita.com/okappy/items/32a7ba7eddf8203c9fa1
class LabeledListSentence(object):
    def __init__(self, words_list, labels):
        self.words_list = words_list
        self.labels = labels

    def __iter__(self):
        for i, words in enumerate(self.words_list):
            yield models.doc2vec.TaggedDocument(words, ['%s' % self.labels[i]])

sentences = LabeledListSentence(m_all, p_all)
model = models.Doc2Vec(
    alpha=0.025,
    min_count=5,
    vector_size=100,
    epoch=20,
    workers=4
)
#Construisez un vocabulaire à partir des phrases que vous avez
model.build_vocab(sentences)
model.train(
    sentences,
    total_examples=len(m_all),
    epochs=model.epochs
)

#Rappel car l'ordre peut changer
tags = model.docvecs.offset2doctag

PCA et dessin

C'est la première fois que j'utilise la bibliothèque PCA, et même si j'en ai tellement appris, c'est incroyable qu'elle puisse être utilisée en deux lignes.

python


from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import japanize_matplotlib

vecs = [model.docvecs[p] for p in tags]
draw_scatter_plot(vecs, ls)

#Dissocier
tag_users = [p.split('**')[0] for p in tags]
tag_docs = [p.split('**')[1] for p in tags]

#Il était difficile de trouver le même degré de couleur en 4 couleurs
cols = ["#0072c2", "#Fc6993", "#ffaa1c", "#8bd276" ]

#Je l'ai écrit de force en une ligne
clusters = [cols[0] if u == tag_users[0] else cols[1] if u == tag_users[1] else cols[2] if u == tag_users[2] else cols[3] for u in lab_users]

#2D parce que c'est un avion
pca = PCA(n_components=2)
coords = pca.fit_transform(vecs)

fig, ax = plt.subplots(figsize=(16, 12))
x = [v[0] for v in coords]
y = [v[1] for v in coords]

#Faites cette boucle pour donner une légende
for i, u in enumerate(set(tag_users)):
    x_of_u = [v for i, v in enumerate(x) if tag_users[i] == u]
    y_of_u = [v for i, v in enumerate(y) if tag_users[i] == u]
    ax.scatter(
        x_of_u,
        y_of_u,
        label=u,
        c=cols[i],
        s=30,
        alpha=1,
        linewidth=0.2,
        edgecolors='#777777'
    )

plt.legend(
    loc='upper right',
    fontsize=20,
    prop={'size':18,}
)
plt.show()

Fait (republier)

Prévoyez avant de faire

--R-kun

résultat

La portée et le chevauchement sont intuitivement proches des attentes

スクリーンショット 2019-12-11 19.16.44.png

fin

En premier lieu, il y a beaucoup de doublons dans les signets, donc je suis désolé de ne pas avoir pu rompre proprement Si les données augmentent un peu plus, j'aimerais faire des recommandations en les transformant en inférences d'utilisateurs.

Désolé d'être en retard (12/11/21: 00)

Recommended Posts

J'ai essayé de visualiser les signets volant vers Slack avec Doc2Vec et PCA
J'ai essayé de visualiser AutoEncoder avec TensorFlow
J'ai essayé de lire et d'enregistrer automatiquement avec VOICEROID2 2
J'ai essayé d'implémenter et d'apprendre DCGAN avec PyTorch
J'ai essayé de lire et d'enregistrer automatiquement avec VOICEROID2
J'ai essayé d'implémenter Grad-CAM avec keras et tensorflow
J'ai essayé de prédire et de soumettre les survivants du Titanic avec Kaggle
[Python] J'ai essayé de visualiser des tweets sur Corona avec WordCloud
J'ai essayé de créer une interface graphique à trois yeux côte à côte avec Python et Tkinter
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé de créer des taureaux et des vaches avec un programme shell
J'ai essayé de résumer les remarques de tout le monde sur le slack avec wordcloud (Python)
J'ai essayé de détecter facilement les points de repère du visage avec python et dlib
J'ai essayé d'implémenter Autoencoder avec TensorFlow
J'ai essayé de commencer avec Hy
J'ai essayé d'implémenter CVAE avec PyTorch
J'ai essayé de résoudre TSP avec QAOA
[Python] J'ai essayé de visualiser la nuit du chemin de fer de la galaxie avec WordCloud!
J'ai essayé de visualiser la tranche d'âge et la distribution des taux d'Atcoder
J'ai essayé d'exprimer de la tristesse et de la joie face au problème du mariage stable.
J'ai essayé de convertir la chaîne datetime <-> avec tzinfo en utilisant strftime () et strptime ()
J'ai essayé de visualiser la reconnaissance générale d'objets de Google NN, Inception-v3 avec Tensorboard
J'ai essayé d'apprendre l'angle du péché et du cos avec le chainer
J'ai essayé de visualiser le texte du roman "Weather Child" avec Word Cloud
J'ai essayé de visualiser le modèle avec la bibliothèque d'apprentissage automatique low-code "PyCaret"
J'ai essayé de visualiser tous les arbres de décision de la forêt aléatoire avec SVG
J'ai essayé de contrôler la bande passante et le délai du réseau avec la commande tc
J'ai essayé de prédire l'année prochaine avec l'IA
J'ai essayé d'implémenter la lecture de Dataset avec PyTorch
J'ai essayé d'utiliser lightGBM, xg boost avec Boruta
J'ai essayé d'apprendre le fonctionnement logique avec TF Learn
J'ai essayé de déplacer GAN (mnist) avec keras
J'ai implémenté DCGAN et essayé de générer des pommes
J'ai essayé d'informer Slack de la mise à jour de Redmine
J'ai essayé de sauvegarder les données avec discorde
J'ai essayé de détecter rapidement un mouvement avec OpenCV
J'ai essayé d'intégrer Keras dans TFv1.1
J'ai essayé de jouer en connectant PartiQL et MongoDB
J'ai essayé la différenciation jacobienne et partielle avec python
J'ai essayé d'obtenir des données CloudWatch avec Python
J'ai essayé la synthèse de fonctions et le curry avec python
J'ai essayé de sortir LLVM IR avec Python
J'ai essayé de détecter un objet avec M2Det!
J'ai essayé d'automatiser la fabrication des sushis avec python
J'ai essayé de prédire la survie du Titanic avec PyCaret
J'ai essayé d'utiliser Linux avec Discord Bot
J'ai essayé d'étudier DP avec séquence de Fibonacci
J'ai essayé de démarrer Jupyter avec toutes les lumières d'Amazon
J'ai essayé de juger Tundele avec Naive Bays
[Introduction au PID] J'ai essayé de contrôler et de jouer ♬
J'ai essayé de faire un processus périodique avec CentOS7, Selenium, Python et Chrome
J'ai essayé de visualiser facilement les tweets de JAWS DAYS 2017 avec Python + ELK
J'ai essayé de créer un bouton pour Slack avec Raspeye + Tact Switch
[Introduction à AWS] J'ai essayé de porter une application de conversation et de jouer avec text2speech @ AWS ♪
J'ai essayé de créer une API de reconnaissance d'image simple avec Fast API et Tensorflow
J'ai essayé d'entraîner la fonction péché avec chainer
J'ai essayé de classer M. Hanyu et M. Hanyu avec le traitement du langage naturel × classificateur Naive Bayes