J'ai touché à Python, mais j'ai peu d'expérience dans la mise en œuvre de l'apprentissage automatique. → Je veux surtout faire quelque chose en utilisant le traitement du langage naturel Avec ce sentiment, j'ai construit un modèle d'estimation de buzz.
Obtenez-le à partir du compte Twitter (Qiita Popular Posts) qui présente les articles tendance à l'aide de l'API Twitter. 3229 données seront collectées, l'URL et les pictogrammes du tweet seront supprimés, puis sauvegardés dans le fichier json.
def retrieveTweets(screenName, count):
global totalIdx
timeLine = t.statuses.user_timeline(screen_name=screenName, count=count)
maxId = 0
for tweetsIdx, tweet in enumerate(timeLine):
maxId = tweet["id"]
addArticleTitles(tweet)
totalIdx += 1
print("Starting additional retrieving...")
retrieveContinuedTweets(screenName, count, maxId)
def retrieveContinuedTweets(screenName, count, maxId):
global totalIdx, isFinished
tmpMaxId = maxId
while True:
timeLine = t.statuses.user_timeline(screen_name=screenName, count=count, max_id=tmpMaxId)
prevMaxId = 0
for tweetsIdx, tweet in enumerate(timeLine):
tmpMaxId = tweet["id"]
addArticleTitles(tweet)
print("totalIdx = {}, prevMaxId = {}, maxId = {}, title = {}\n".format(totalIdx, prevMaxId, tmpMaxId, trendArticleTitles[totalIdx]["articleTitle"]))
if prevMaxId == 0 and totalIdx % 200 != 0:
isFinished = True
break
prevMaxId = tmpMaxId
totalIdx += 1
if isFinished:
print("Finished collecting {} qiita_trend_titles.".format(totalIdx))
break
def addArticleTitles(tweet):
global trendArticleTitles
tmpTitle = re.sub(r"(https?|ftp)(:\/\/[-_\.!~*\'()a-zA-Z0-9;\/?:\@&=\+\$,%#]+)", "", tweet["text"]) #Supprimer l'URL dans les tweets
tmpTitle = ''.join(s for s in tmpTitle if s not in emoji.UNICODE_EMOJI)
articleTitle = tmpTitle[:len(tmpTitle)-1] #Retirez l'espace demi-largeur à la fin
datum = {"articleTitle": articleTitle}
trendArticleTitles.append(datum)
Utilisez l'API Qiita pour obtenir les titres des articles réguliers qui ne sont pas en vogue. Ici, 9450 données ont été collectées et sauvegardées dans un fichier json ainsi que des titres d'articles de tendance.
articleTitles = []
idx = 0
print("Starting collecting article titles...")
for page in range(3, 101):
#Exclure les premières pages pour exclure les articles des comptes de spam
params = {"page": str(page), "per_page": str(per_page)}
response = requests.get(url, headers=headers, params=params)
resJson = response.json()
for article in resJson:
if article.get("likes_count") < notBuzzThreshold:
title = article.get("title")
articleTitles.append({"articleTitle": title})
print("{}th article title = {}, url = {}".format(idx, title, article["url"]))
idx += 1
print("Finished collecting {} qiita_article_titles.".format(idx))
Commencez par charger les deux types de données de titre d'article collectées ci-dessus. Tout en ajoutant un indicateur indiquant s'il s'agit d'un article de tendance, nous le terminerons comme une seule donnée. Au cas où, mélangez le contenu des données combinées.
Encore une fois, le fichier json est vidé à la fin et la collecte de données est terminée.
mergedData = []
for datum in trendData:
mergedData.append({
"articleTitle": datum["articleTitle"],
"isTrend": 1
})
for datum in normalData:
mergedData.append({
"articleTitle": datum["articleTitle"],
"isTrend": 0
})
#Mélangez l'ordre des résultats combinés
random.shuffle(mergedData)
print("Finished shuffling 'Merged Article Titles'.")
J'ai essayé de construire un modèle d'estimation à l'aide de Naive Bayes, mais je ne savais pas par quoi commencer. Par conséquent, j'ai examiné Naive Bayes lui-même et essayé un article qui implémente la détection de spam dans Naive Bayes afin que je puisse en avoir une idée avant cette implémentation.
Chap2_SpamDetection.md Cela a été expliqué à l'aide d'un exemple réel, et j'ai pu confirmer la partie telle que "Qu'est-ce que Naive Bayes en premier lieu?"
[WIP] Introduction car le simple classificateur Bayes n'est pas du tout simple Dans l'article qui montre la couleur de la formule, j'ai pu confirmer le type de calcul effectué.
Maintenant que j'ai beaucoup appris sur Naive Bayes, je suis passé à la mise en œuvre pratique. J'ai continué le long de la ↓. Apprentissage automatique ~ Classification du courrier indésirable (classificateur Naive Bayes) ~
Maintenant que vous avez une idée de Naive Bayes, il est temps d'entrer dans le sujet principal. J'écrirai sur les parties qui ont été modifiées à partir de la mise en œuvre de l'article utilisé dans la pratique.
Puisque l'ensemble de données de détection de spam est en anglais, il peut être jeté directement dans scicit-learn, mais le titre de l'article Qiita ne le fait pas. Tout d'abord, ajoutez MeCab et ipadic-NEologd afin que vous puissiez bien diviser les mots en japonais. (Le résultat de la division a été obtenu avec CountVectorizer, mais ce n'était pas naturel.)
Je me suis principalement référé au site ci-dessous.
À partir de la mise en œuvre de la pratique de détection de spam, nous avons ajouté ce qui suit:
def getStopWords():
stopWords = []
with open("./datasets/Japanese.txt", mode="r", encoding="utf-8") as f:
for word in f:
if word != "\n":
stopWords.append(word.rstrip("\n"))
print("amount of stopWords = {}".format(len(stopWords)))
return stopWords
def removeEmoji(text):
return "".join(ch for ch in text if ch not in emoji.UNICODE_EMOJI)
stopWords = getStopWords()
tagger = MeCab.Tagger("mecabrc")
def extractWords(text):
text = removeEmoji(text)
text = neologdn.normalize(text)
words = []
analyzedResults = tagger.parse(text).split("\n")
for result in analyzedResults:
splittedWord = result.split(",")[0].split("\t")[0]
if not splittedWord in stopWords:
words.append(splittedWord)
return words
Si vous passez la méthode de fractionnement de mots à l'analyseur d'arguments de CountVectorizer, il semble que le japonais se divise également bien. génial.
vecCount = CountVectorizer(analyzer=extractWords, min_df=3)
Nous avons préparé trois textes pour la prédiction: "" "J'ai sorti l'application" ,
"Unity tutorial" ,
"Git command memo" `.
"J'ai essayé de publier l'application" est censé être "bourdonnant".
De toute évidence, le nombre de mots est faible. Je pense qu'il n'a pas été divisé normalement.
word size: 1016
word content: {'De': 809, 'ms': 447, 'nginx': 464, 'django': 232, 'intellij': 363}
Train accuracy = 0.771
Test accuracy = 0.747
[0 0 0]
Il semble que les mots peuvent être divisés, mais il y a beaucoup de mots ... Le classement est comme prévu.
word size: 3870
word content: {'De': 1696, 'MS': 623, 'Teams': 931, 'À': 1853, 'notification': 3711}
Train accuracy = 0.842
Test accuracy = 0.783
[1 0 0]
Le nombre de mots a été réduit et la précision des données de test a légèrement augmenté. J'ai ressenti l'importance du prétraitement.
word size: 3719
word content: {'MS': 623, 'Teams': 931, 'À': 1824, 'notification': 3571, 'Faire': 1735}
Train accuracy = 0.842
Test accuracy = 0.784
[1 0 0]
La précision des données d'entraînement a légèrement diminué, mais la précision des données de test a augmenté en conséquence. De plus, j'ai oublié d'afficher la probabilité de classification, je vais donc l'afficher ici. Le texte que j'imaginais bourdonnant a été honnêtement surpris avec une probabilité plus élevée que ce à quoi je m'attendais. (Ce n'est pas fiable à moins que vous ne l'essayiez avec plus de textes ...)
word size: 3700
word content: {'MS': 648, 'Teams': 955, 'À': 1838, 'notification': 3583, 'Faire': 1748}
[1 0 0]
[[0.23452364 0.76547636]
[0.92761086 0.07238914]
[0.99557625 0.00442375]]
Train accuracy = 0.841
Test accuracy = 0.785
Cette fois, il semblait que le changement de précision était dans la plage de l'erreur. Comme je ne pouvais garantir que les termes minimaux contenus dans NEologd, j'ai pensé que la précision pouvait être améliorée en couvrant la vectorisation des termes techniques. Après cela, il semble que la précision s'améliorera même si vous extrayez des mots importants du titre de l'article et du contenu de l'article avec TF-IDF etc. et que vous les utilisez.
Recommended Posts