自然言語処理でツイートがバズるかをちゃんと予測する


この記事は[ニフティグループ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nifty)の7日目の記事です。

# ツイートがバズるかを予測したい

昨年、[自然言語処理でツイートがバズるかを予測しようとした話](https://qiita.com/iNakamura/items/ae24c9f511bea4ae19cb)
という記事であるツイートがバズるかを予測してみました。

最近、社内ではAIを活用するという動きが活発になってきており、
機械学習畑出身の自分もだいぶさまざまなところに投入されております。

その中でSNS分析を行った際に良質なデータが集まったので、再度ツイートのバズを予測してみたいと思います。

# 自然言語処理とは
自然言語処理は、人が話している言葉をコンピュータに認識させることの一連の技術を指します。

プログラミング言語はパターンに沿って設計されているので、コンピュータが解析するにも苦労しないのですが、人間が話している言葉はパターンが複雑だったり例外が多く、機械学習が活発に研究されている今でも難しい分野と言われています。

# 近年の自然言語処理
難しいと言われていた自然言語処理も深層学習の登場でかなり改善されており
近年ではGPT-3という自然言語処理モデルがほぼ人間のような文章生成を可能にしているというニュースもあります。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おもしろい<br><br>GPT-3生成のブログ、ハッカーニュースで1位に<a href="https://t.co/db2lXhegra">https://t.co/db2lXhegra</a><br>『彼のブログが完全にAIが生成したものだと気づいた人はほとんどいなかった。何人かは「購読」を押した』<br><br>ブログ作成者「実際には超簡単だった、それが怖いところだった」</p>&mdash; 小猫遊りょう（たかにゃし・りょう） (@jaguring1) <a href="https://twitter.com/jaguring1/status/1295206985198002176?ref_src=twsrc%5Etfw">August 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">GPT-3は定期的にバズる<br><br>文章生成AI「GPT-3」がRedditで1週間誰にも気付かれず人間と会話していたことが判明<a href="https://t.co/sDWjTU1QcS">https://t.co/sDWjTU1QcS</a><br>Redditユーザー「この人は一体どうやってあんなに文章量が多くて内容も深い投稿を、凄まじい速度で投稿しているんでしょうか？」<br><br>それをきっかけにGPT-3と疑われる</p>&mdash; 小猫遊りょう（たかにゃし・りょう） (@jaguring1) <a href="https://twitter.com/jaguring1/status/1314329079428964353?ref_src=twsrc%5Etfw">October 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

「[Talk to Transformer](https://app.inferkit.com/demo)」というサイトでは、GPT-3の前身のGPT-2というモデルで誰でも文章生成を楽しむことができます。
（GPT-3も開発元のOpenAIがAPIを公開し始めているので、人間と見分けのつかない文章生成が完成するまで時間の問題でしょう・・・）

# ツイートのバズを予測する
それではあるツイートに対して
そのツイートがバズるかを事前に予測する機械学習モデルを構築していきます。

近年の自然言語処理の進歩は文章生成についてですが
今回の問題は「あるツイートがバズるかバズらないか」の2値分類問題になるので
高度な自然言語処理モデルは必要ありません。
（なんなら深層学習も使いません・・・）

## データを集める

### バズを定義する
去年は上位200位のアカウントのツイートという乱暴なデータ収集を行いました。
その結果、以下のようなことが起こっていました。

- バズるかよりもフォロワーが多くなるツイートの分類になってしまっている
- Youtuberが多く、「動画をあげました」というツイートがバズると予測されていた
- 企業の定型文や地震速報の形式などがバズるという予測がされていた

ツイートの秀逸さ以外で人気がある人達のツイートデータのため
本来予測したいバズるかが全く予測できていませんでした。

そこで今回はRT数2000以上のツイートデータをバズると定義し、真面目に収集したいと思います。

### スクレイピング禁止・・・？

そこでTwitterからデータを集めたいのですが
Twitter APIは1週間以上前のデータはけっこうな額の課金をしないと集められません。
（これが原因で去年の自分は雑なデータ収集をしていました）

じゃあスクレイピングかという話ですが、スクレイピングは規約で明確に禁止されています。
![scraping forbidden](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326601/8d6a4e1c-2473-eafe-f8b0-c6ae2c507e24.png)

というわけで**手作業で30000ツイートくらい収集**しました。
（8月頃の業務中の自分が）
![hand scrape](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326601/124e43e0-00a1-989a-9636-fa73ec002c0d.png)

![scrape data](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326601/54d26064-12dd-a26d-3d99-8cd7dc7478a0.png)

数年前に学会に行ったときに
卒業研究のために20000枚の画像をアノテーションしましたという人に会いましたが
機械学習はだいたいデータ集めが辛くて、データ集めが9割だなと思います。

## 学習する

データを整形し学習をしてみます。

```
11337  __label__Buzz                 レバノン爆発の原因物質は2015年に韓国から輸入した硝酸アンモニウム
12203  __label__Buzz                             極小ネタ（さすがにピュアな3歳下はかわいい）
11059  __label__Buzz                          超能力者同士の戦いにしか見えないトルコのデモの画像
3251   __label__Buzz               スカラビアの宴でうっかりはしゃいじゃったオクタヴィネルの爽やか３コマ漫画
2414   __label__Buzz   GO!senzoたちがヘリで帰ってくる ナマ足 割り箸 マーメイド☀️ はやかわ #精霊馬...
15561  __label__Buzz                               #ツイステファンアート 仲良しオクタビア
2270   __label__Buzz                                         プリコネ2期〜！！！
22743  __label__Buzz                                たまに遭遇する #ツイステファンアート
6472   __label__Buzz   【ミカサデコ&カフェ】 @原宿駅から徒歩5分 厚みが半端ないリコッタパンケーキを食べられる...
17235  __label__Buzz                       王様ゲームで真っ赤になるオフ会なかよし部【プリコネ漫画】
```

今回も[fastText](https://github.com/facebookresearch/fastText)を使って学習をしてみます。
詳しくは：[FacebookのfastTextでFastに単語の分散表現を獲得する](https://qiita.com/icoxfog417/items/42a95b279c0b7ad26589)

学習済みモデルとして[fastTextの学習済みモデルを公開しました](https://qiita.com/Hironsan/items/513b9f93752ecee9e670)のNeologd版を使わせていただきました。

```
% ./fasttext supervised -input tweet_data/tweet_data_train.txt -output result/tweet -dim 300 -lr 0.1 -wordNgrams 2 -minCount 1 -epoch 100 -thread 4 -pretrainedVectors model.vec
Read 0M words
Number of words:  100873
Number of labels: 2
Progress: 100.0% words/sec/thread:  615466 lr:  0.000000 loss:  0.013649 ETA:   0h 0m
% ./fasttext test result/tweet.bin tweet_data/tweet_data_test.txt
N	5277
P@1	0.689
R@1	0.689
```

テストデータに対して68.9%の正答率です。
ランダムに予測するよりもちょっと当たりそうぐらいですね・・・。

## 実際に予測する

今回のモデルで実際にバズったツイートを予測してみます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">精神衛生上よろしくないタイプのトランプが届いた <a href="https://t.co/dqKHE5WJ9H">pic.twitter.com/dqKHE5WJ9H</a></p>&mdash; かる🎧Kalud🦊 (@kldry) <a href="https://twitter.com/kldry/status/1304397956989112325?ref_src=twsrc%5Etfw">September 11, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

最近延々とサーバーエラーと戦っています。

```
__label__notBuzz, 0.88015
```
**バズらない**
(実際はバズ）


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【エンジニア用語解説】<br><br>「完全に理解した」<br>製品を利用をするためのチュートリアルを完了できたという意味。<br><br>「なにもわからない」<br>製品が本質的に抱える問題に直面するほど熟知が進んだという意味。<br><br>「チョットデキル」<br>同じ製品を自分でも１から作れるという意味。または開発者本人。</p>&mdash; 伊藤 祐策(パソコンの大先生) (@ito_yusaku) <a href="https://twitter.com/ito_yusaku/status/1042604780718157824?ref_src=twsrc%5Etfw">September 20, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

強制的にiOSエンジニアにさせられたので、iOS完全理解しました。

```
__label__notBuzz, 0.877977
```
**バズらない**
(実際はバズ）

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">SES企業に、何をトチ狂っていたのかわからないが、とても残念ながら入ってしまった新入社員へ。<br>「配属先の希望を聞くよ」と言われたら、以下の【JRの駅】のどれかをおすすめします。<br>・渋谷<br>・新宿<br>・秋葉原<br><br>間違っても<br>・東陽町<br>・茅場町<br>・豊洲<br>・お台場<br>は選んではいけません。死にます。</p>&mdash; くわっちょ@社畜犬 (@kuwaccho0711) <a href="https://twitter.com/kuwaccho0711/status/981158131806777344?ref_src=twsrc%5Etfw">April 3, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

弊社の最寄りは新宿駅です。

```
__label__notBuzz, 0.623716
```
**バズらない**
(実際はバズ）

# 敗因はなにか

今回実際のツイートを予測してみましたが、ほとんど正しく予測できませんでした。

理由としては2つあると考えられます。

1つはデータ数がそもそも足りないこと。
手作業で30000ツイートほど収集しましたが、機械学習の文脈ではかなり少ないデータ数です。
去年は機械的に収集しただけあって、60万ツイートほど集められていたので、データ数はかなり不足していたと考えられます。

もう1つがリツイートをバズの基準にしたことにあります。
検索してみるとわかるのですが、最近のTwitterではRT&フォローでプレゼントということが企業のアカウントで頻繁に行われています。
そうなってくると、リツイートされやすいツイートというのは必然的に企業のプレゼント系のツイートになってしまい、全体的な傾向もそれに引っ張られます。

会社でSNS分析をやった際にもデータクレンジングに多くの時間を使ったのですが
SNSはノイズがかなり大きいのでそれを除去することが重要になってくると再認識しました。

来年もリベンジしたいと思います。（希望的観測）

---

弊社ではエンジニアを募集しています（多分）

普段はWEBアプリケーションを作りつつ
機械学習を嗜む環境へぜひご応募ください。

[ニフティ株式会社採用情報](https://recruit.nifty.co.jp/)