Introduction à elle faite avec Python ~ Projet d'automatisation Tinder ~ Épisode 5

table des matières

Ce que j'ai fait Événements principaux
Épisode 1 Balayage automatique à droite
Épisode 2 Envoi automatique de messages Assorti avec une femme
Épisode 3 Bibliothèque Échangé LINE avec une femme assortie
numéro 3.Épisode 5 Réacquisition du jeton d'accès Vous ne pouviez pas obtenir de jetons avec le code précédent
Épisode 4 Collecte de données Les réponses LINE ne viennent plus
Épisode 5 Texte du profil d'analyse des données Les produits d'information ont été recommandés par des personnes avec lesquelles je suis devenu ami
Épisode 6 Édition d'image d'analyse de données Une vraie fille de connaissance m'appelle récemment tard dans la nuit(?)

Le code peut être visualisé depuis [GitHub] git.

Synopsis jusqu'à la dernière fois

Situation récente

J'étais occupé à préparer la conférence et quand je m'en suis rendu compte, cela faisait plus de deux mois depuis le dernier article. Cependant, le robot d'exploration a fonctionné tout le temps, j'ai donc beaucoup de données que j'ai commencé à collecter depuis la dernière fois. Elle ne peut pas le faire comme d'habitude.

L'analyse des données

De nombreuses données ont été collectées. Il y a 10632 femmes qui ont balayé. 72 d'entre eux correspondaient. Cela ne correspond pas à ce à quoi je m'attendais. La dernière fois, j'ai enregistré les données du tableau dans la feuille de calcul et les données d'image dans Google Drive, j'ai donc commencé par les télécharger. Lors du téléchargement d'une feuille de calcul, vous pouvez sélectionner plusieurs formats de fichier, mais lorsque vous le téléchargez avec csv ou tsv, les sauts de ligne dans le texte du profil et les virgules écrites par des étrangers dans le texte du profil sont mauvais et c'était inutilement gênant. Alors enregistrez-le au format .xlsx. De plus, il y avait environ 25 000 images de profil, donc le téléchargement a pris beaucoup de temps. L'analyse se fait sur le notebook jupyter.

Veuillez noter que ces données sont une vérification des données collectées en fonction de mon profil, donc si vous l'exécutez, le résultat peut différer. [^ 1] Soyez prudent.

Jetez un œil aux données

Tout d'abord, regardons les données des personnes correspondantes.

analytics.py


import pandas as pd
import numpy as np
from tqdm.notebook import tqdm
import matplotlib.pyplot as plt
import seaborn as sns
from collections import Counter


filePath="data/tinder.xlsx"
df=pd.read_excel(filePath)
df.set_index("id", inplace=True)

match = df[df["match"]==1]

Y a-t-il quelqu'un que vous ne reconnaissez pas? ??

Viennent ensuite les données de la personne qui ne correspond pas.

analytics.py


unmatch = df[df["match"]==0]

Cela ressemble à Pat, mais je pense que la personne correspondante remplit le texte du profil plus fermement. Allons vérifier. Il est difficile de définir un "texte de profil bien rempli", mais pour l'instant, vérifions simplement le nombre de caractères dans le texte du profil.

analytics.py


%matplotlib inline
sns.distplot(unmatch["bio"].apply(lambda w:len(str(w))), color="b", bins=30)
sns.distplot(match["bio"].apply(lambda w:len(str(w))), color="r", bins=30)

Le résultat est le suivant. Ceux qui correspondent au rouge et ceux qui ne correspondent pas au bleu. bio-length.png

Après tout, je pense que le rouge a moins de caractères proches de zéro que le bleu. En fait, il semble qu'il existe de nombreux comptes qui n'écrivent pas un seul caractère dans le profil pour ceux qui ne correspondent pas. Les comptes avec un profil vide sont moins susceptibles de correspondre même si vous faites glisser votre doigt vers la droite, il semble donc préférable de ne pas glisser.

Afficher le texte du profil en détail

Analyse morphologique

Tout d'abord, je voudrais vérifier les mots inclus dans la phrase du profil. Pour les phrases de profil, l'analyse morphologique est réalisée à l'aide du moteur d'analyse morphologique MeCab [1] et du dictionnaire étendu mecab-ipadic-NEologd [2].

Installation

Vous pouvez installer MeCab avec `` pip install mecab-python3 ''. Pour la méthode d'installation de mecab-ipadic-NEologd, le texte officiel [3] est très bien organisé, veuillez donc vous y référer. Vous pouvez choisir différentes options, mais pour ceux qui sont vraiment gênants

$git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git ~/neologd
$echo yes | ~/neologd/bin/install-mecab-ipadic-neologd -n -a

Ensuite, vous pouvez l'installer.

Partage de mots

Appelez mecab de Python pour diviser votre déclaration de profil mot par mot. L'appel simple de mecab utilise un dictionnaire standard, alors spécifiez NEologd comme option. L'emplacement du dictionnaire peut être obtenu avec ```echo mecab-config --dicdir" / mecab-ipadic-neologd "` ``.

mecab.py


import subprocess
import MeCab

cmd = 'echo `mecab-config --dicdir`"/mecab-ipadic-neologd"'
path = (subprocess.Popen(cmd, stdout=subprocess.PIPE,
                           shell=True).communicate()[0]).decode('utf-8')
m = MeCab.Tagger("-d {0}".format(path))

print(m.parse("Elle a dansé amoureuse de Penpainappoappopen."))
#>>
#Sa nomenclature,Synonyme,Général,*,*,*,Petite amie,Petite amie,Petite amie
#Est un assistant,Assistance,*,*,*,*,Est,C,sensationnel
#Nomenclature du stylo Appo,Nomenclature propriétaire,Général,*,*,*,Pen-Pineapple-Apple-Pen,Pen Ananas Apple Pen,Pen Ananas Apple Pen
#Et des mots auxiliaires,Assistants parallèles,*,*,*,*,Quand,À,À
#Danse substantif,Nomenclature propriétaire,Général,*,*,*,Danse d'amour,Danse d'amour,Danse d'amour
#Auxiliaire,Assistant de cas,Général,*,*,*,À,Wo,Wo
#Verbe dansant,Indépendance,*,*,Cinq étapes, La ligne,Connexion continue,Danse,Impair,Impair
#Verbe auxiliaire,*,*,*,Spécial,Forme basique,Ta,Ta,Ta
#.. symbole,Phrase,*,*,*,*,。,。,。
#EOS

Mots souvent utilisés par les personnes correspondantes

Ceci est utilisé pour extraire les mots inclus dans la phrase de profil de chacune des personnes appariées et non appariées.

analytics.py


def getWord(df):
    retval = []
    for bio in df.bio:
        parse = m.parse(str(bio)).strip().split("\n")
        for p in parse:
            if ("\t" in p) == False:
                continue
            word, desc = p.split("\t")
            if desc.split(",")[0] in ("nom", "verbe", "adjectif", "形容verbe", "Coalm", "adverbe", "conjonction", "感verbe", "symbole"): # 助詞と助verbeを除きたかった
                retval.append(word)
    return retval

bio_match = getWord(match)
bio_unmatch = getWord(unmatch)

La liste des mots obtenus est affichée par ordre de fréquence d'occurrence. Tout d'abord, de la personne qui correspond.

analytics.py


df_bio_match = pd.DataFrame.from_dict(
    Counter(bio_match), orient="index").reset_index().rename(columns={"index":"word",0:"count"})
sns.barplot(data=df_bio_match.sort_values(
    "count", ascending=False)[:20], x="word", y="count")
plt.xticks(rotation="vertical")

bio-match.png

Le tofu qui se produit est quelque chose comme un espace vide. Peut-être thinsp? Je me demandais qui utilisait ∇ (Nabla), alors je l'ai vérifié et j'ai trouvé qu'il était utilisé pour des lettres faciales comme (・ ∇ ・). Vient ensuite la personne qui ne correspond pas.

analytics.py


df_bio_unmatch = pd.DataFrame.from_dict(
    Counter(bio_unmatch), orient="index").reset_index().rename(columns={"index":"word",0:"count"})
sns.barplot(data=df_bio_unmatch.sort_values(
    "count", ascending=False)[:20], x="word", y="count")
plt.xticks(rotation="vertical")

bio-unmatch.png

Il semble y avoir une différence dans la tendance, il semble que ce ne soit pas le cas ... Par exemple, on peut voir que les personnes qui correspondent ont tendance à ne pas percer les phrases. Aussi, bien qu'il y ait beaucoup de gens qui écrivent "comme" en kanji avec ou sans correspondance, aucun d'entre eux ne correspond à ceux qui écrivent "suki" en hiragana. ~~ Est-ce une mine terrestre? ~~ Pour être honnête, je ne pense pas que ce soit dans la fourchette d'erreur car le nombre d'échantillons de personnes appariées est petit, mais cela vaut peut-être la peine de s'en souvenir.

Vectorisation des phrases

Enfin, vectorisons la déclaration de profil à l'aide de Doc2Vec. Il y a quelques années, DNN, qui vectorise le mot Word2Vec, est devenu un gros sujet dans le domaine de la PNL, mais Doc2Vec est un algorithme qui l'applique à des phrases plutôt qu'à des mots. L'explication de Word2Vec a été utile dans [4], et l'explication de Doc2Vec a été utile dans [5] [6]. L'implémentation utilise une bibliothèque appelée gensim [7]. Veuillez l'installer avec `` pip install gensim ''. Pour le code spécifique, je me suis référé à [8].

analytics.py


#Divisez les données en données d'entraînement et données de test
df_train, df_test = train_test_split(df, random_state=8888)

#Divisez les phrases de profil en mots à l'aide de MeCab
m_wakati = MeCab.Tagger("-d {0} -Owakati".format(path)) #Options MeCab-En ajoutant Owakati, les mots sont séparés par des espaces sans générer de mots partiels.
bios=[]
for bio in df_train.bio:
    bio = m_wakati.parse(str(bio)).strip()
    bios.append(bio)

#Convertir les données dans un format pouvant être traité par gensim
trainings = [TaggedDocument(words = data.split(),tags = [i]) for i,data in enumerate(bios)]

#Apprendre doc2vec
doc2vec = Doc2Vec(documents=trainings, dm=1, vector_size=300, window=4, min_count=3, workers=4)

#Obtenez un vecteur de données d'entraînement
X_train = np.array([doc2vec.docvecs[i] for i in range(df_train.shape[0])])

#Obtenez l'étiquette de réponse correcte pour les données d'entraînement
y_train = df_train["match"]

#Obtenez un vecteur de données de test et une étiquette correcte
X_test = np.array([doc2vec.infer_vector(m.parse(str(bio)).split(" ")) for bio in df_test.bio])
y_test = df_test["match"]

Visualisons le texte vectorisé en utilisant PCA. Tout d'abord, à partir des données d'entraînement.

analytics.py


from sklearn.decomposition import PCA

pca = PCA()
X_reduced = pca.fit_transform(X_train)

plt.scatter(X_reduced[y_train==0][:,0], X_reduced[y_train==0][:,1], c="b", label="No Match")
plt.scatter(X_reduced[y_train==1][:,0], X_reduced[y_train==1][:,1], c="r", label="Match")
plt.legend()

pca_train.png Pour ceux qui ne correspondent pas, il y a un certain nombre de personnes qui ont une deuxième composante principale importante, tandis que la deuxième composante principale de celles qui correspondent est généralement autour de 0. Regardons également les données de test.

analytics.py


X_test_reduced = pca.transform(X_test)

plt.scatter(X_test_reduced[y_test==0][:,0], X_test_reduced[y_test==0][:,1], c="b", label="No Match")
plt.scatter(X_test_reduced[y_test==1][:,0], X_test_reduced[y_test==1][:,1], c="r", label="Match")
plt.legend()

pca_test.png

Ceux qui correspondent peuvent voir que la deuxième composante principale est regroupée près de 0.

Apprentissage automatique

Classification à l'aide de svm

Maintenant que les phrases ont été vectorisées, appliquons l'apprentissage automatique pour les classer. Classez les vecteurs de déclaration de profil à l'aide d'une machine à vecteurs de support. Puisque les données manipulées cette fois sont des données déséquilibrées extrêmement biaisées, si la limite de décision est tracée docilement, tous les profils seront jugés comme "ne correspondant pas". Cela ne sert à rien. En premier lieu, en regardant en arrière sur ce que je voulais faire cette fois, je ne voulais pas améliorer la précision de l'apprentissage automatique, mais elle le voulait. Focalisation sur chaque élément de la matrice de confusion,

La description Remarques
TP Déterminé à correspondre à la personne qui correspond réellement C'est ce que vous recherchez
TN Jugez que les personnes qui ne correspondent pas réellement ne sont pas appariées Vous pouvez réduire le balayage à droite inutile
FP Déterminé à faire correspondre les personnes qui ne correspondent pas réellement Le balayage à droite est perdu une fois
FN Jugez que la personne qui correspond réellement ne correspond pas Je ne peux pas rencontrer la personne destinée

Evidemment FN est le pire et je veux l'éviter à tout prix. D'un autre côté, il est souhaitable que FP ne se produise pas, mais peu importe si cela se produit un peu. Par conséquent, dans cette tâche, il est nécessaire que le rappel soit aussi élevé que possible. En revanche, la précision et les valeurs F sont acceptables même si elles sont faibles. Bien sûr, si vous prédisez que tous les cas "correspondent", vous pouvez obtenir un rappel élevé en échange de la destruction de la précision et de la valeur F [^ 2], nous avons donc introduit l'apprentissage automatique pour éviter cela. Pour cette raison, si le rappel diminue, je dois dire que c'est une chute. Par conséquent, cette fois, nous allons adopter une stratégie pour estimer la probabilité d'appariement par Regressor et fixer un seuil assez bas pour éliminer uniquement les «méchants qui ne sont évidemment pas susceptibles de correspondre». Le soupçon est un coup droit. Auc est utilisé comme indice d'évaluation.

analytics.py


from sklearn.svm import SVR
from sklearn.metrics import roc_auc_score

model = SVR(C=100.0)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(roc_auc_score(y_test, y_pred))
#>>0.6196

Over auc0.6! N'est-ce pas un très bon résultat? Des paramètres de seuil spécifiques seront définis une fois l'image analysée. L'article est devenu long, je suis donc ici aujourd'hui. Veuillez attendre avec impatience la prochaine édition d'image de profil.

L'épisode 6 est [ici] ep.6

Les références

[1]https://taku910.github.io/mecab/ [2]https://github.com/neologd/mecab-ipadic-neologd [3]https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md [4] Yasuki Saito, Deep Learning from scratch ❷ - Traitement du langage naturel [5] https://kitayamalab.wordpress.com/2016/12/10/doc2vec paragraph-vector-algorithm / [6]https://deepage.net/machine_learning/2017/01/08/doc2vec.html [7]https://radimrehurek.com/gensim/index.html [8]https://qiita.com/asian373asian/items/1be1bec7f2297b8326cf

[^ 1]: Je voudrais vérifier quel genre de différence se produira si la même expérience est menée entre beau et moi. Non, vous ne voudrez peut-être pas le voir. [^ 2]: Et cela a été réalisé grâce à la stratégie de balayage qui avait été mise en œuvre jusqu'à présent, appelée balayage tout à droite.

Recommended Posts

Introduction à elle faite avec Python ~ Projet d'automatisation Tinder ~ Épisode 6
Introduction à elle faite avec Python ~ Projet d'automatisation Tinder ~ Épisode 5
Système de notation IPynb réalisé avec TA d'introduction à la programmation (Python)
[Introduction à Python] Utilisons foreach avec Python
[Python] Introduction facile à l'apprentissage automatique avec python (SVM)
Introduction à l'intelligence artificielle avec Python 1 «Théorie des algorithmes génétiques»
Markov Chain Artificial Brainless avec Python + Janome (1) Introduction à Janome
Chaîne de Markov artificielle sans cervelle avec Python + Janome (2) Introduction à la chaîne de Markov
Introduction à l'intelligence artificielle avec Python 2 «Pratique de l'algorithme génétique»
Introduction à Tornado (1): Framework Web Python démarré avec Tornado
Introduction au vol en formation avec Tello edu (Python)
Introduction à Python avec Atom (en route)
Introduction au modèle linéaire généralisé (GLM) par Python
[Introduction à l'application Udemy Python3 +] 9. Tout d'abord, imprimez avec print
Introduction au langage Python
Introduction à OpenCV (python) - (2)
[Introduction à Python] Comment itérer avec la fonction range?
[Chapitre 5] Introduction à Python avec 100 coups de traitement du langage
Introduction au traitement parallèle distribué Python par Ray
Note de lecture: Introduction à l'analyse de données avec Python
J'ai essayé de faire d'Othello pour enseigner Python3 aux enfants (6) Final
[Chapitre 3] Introduction à Python avec 100 coups de traitement du langage
[Chapitre 2] Introduction à Python avec 100 coups de traitement du langage
[Automatisation] Utilisez GitLab avec Python pour faciliter la gestion des requêtes
[Chapitre 4] Introduction à Python avec 100 coups de traitement du langage
Introduction à Python Django (2) Win
J'ai créé un package pour filtrer les séries chronologiques avec python
Connectez-vous à Wikipedia avec Python
Publiez sur Slack avec Python 3
J'ai créé une application de livre simple avec python + Flask ~ Introduction ~
20200329_Introduction à l'analyse de données avec Python 2nd Edition Personal Summary
Convertir le projet Scratch en Python
Mayungo's Python Learning Episode 3: J'ai essayé d'imprimer des nombres
Introduction à Python pour les utilisateurs de VBA - Appeler Python depuis Excel avec xlwings -
Basculer python vers 2.7 avec des alternatives
Écrire en csv avec Python
[Introduction à Python] <liste> [modifier le 22/02/2020]
Introduction à Python (version Python APG4b)
Une introduction à la programmation Python
[Raspi4; Introduction au son] Enregistrement stable de l'entrée sonore avec python ♪
J'ai fait un blackjack avec Python.
Othello fait avec python (comme GUI)
J'ai créé wordcloud avec Python.
Introduction à Python pour, pendant
[Introduction à Python] Comment obtenir des données avec la fonction listdir
[Introduction à Udemy Python3 + Application] 51. Soyez prudent avec les arguments par défaut
Activé pour convertir PNG en JPG avec Pillow of Python
J'ai créé une bibliothèque qui lit facilement les fichiers de configuration avec Python
Une histoire sur l'ajout d'une API REST à un démon créé avec Python
[Introduction à Python] Comment fractionner une chaîne de caractères avec la fonction split
J'ai lu "Renforcer l'apprentissage avec Python de l'introduction à la pratique" Chapitre 1
Introduction à la modélisation statistique bayésienne avec python ~ Essai de régression linéaire avec MCMC ~
[Introduction] Je veux créer un robot Mastodon avec Python! 【Débutants】
Sentons-nous comme un chercheur de matériaux avec python [Introduction à pymatgen]
De l'introduction de JUMAN ++ à l'analyse morphologique du japonais avec Python
J'ai lu "Renforcer l'apprentissage avec Python de l'introduction à la pratique" Chapitre 2
[Présentation de l'application Udemy Python3 +] 58. Lambda
[Présentation de l'application Udemy Python3 +] 31. Commentaire
Python: comment utiliser async avec