テキストマイニングによるTwitter個人アカウントの性格推定
はじめに
PyConJP 2018で「テキストマイニングによるTwitter個人アカウントの性格推定」というタイトルでLTをさせていただきました。
普段はサーバーサイドエンジニアとしてスマホアプリのバックエンドサーバー開発を主にPython/Djangoで行っています。
LT参加の動機は、Pythonを使っている身として機械学習に触れてみたかったからです。
Webアプリケーション開発でしかPythonを使ったことがありませんでしたが、Pythonといえばデータサイエンスのイメージがあります。
採択されてもされなくても、PyConJPのLTという機会で普段は知らないPythonの一面を掘り下げてみようと思いました。
スライド
YouTube
Gihyo
PyConJPの公式カンファレンスレポートで紹介していただきました。
正直「ちょっとストーカーの話っぽいけど大丈夫なの?」とスタッフ同士顔を見合わせる場面もあったのですが,終わってみると真面目でユーモアもある発表だったと思います。
Twitterの反応
Twitterで嬉しい反応をたくさんいただきました!ありがとうございます!
Twitterアカウントの性格推定
ツイートの収集
まずはツイートの収集です。Twitter社が提供するTwitter APIを利用してツイートを取得します。
クライアントの実装として、すぐにパッと思い付くのは requests
を用いた実装です。
HTTP for Humans
とデカデカと主張しているように、直感的にHTTPの通信を実装できます。
これは urllib2
の使いにくさを酷くディスった表現ですが、Python3で urllib.request
が標準ライブラリとして提供されている今、
こちらを使うのも一つの選択肢ではないかと思います。
urllib2
と比べ格段に使いやすくなっています。
urllib.request --- URL を開くための拡張可能なライブラリ — Python 3.9.1 ドキュメント
例えば、AWS LambdaをPython3で使う場合は外部ライブラリをimportするためには少々手間がかかるため、 urllib.request
を選択するのが良いと思います。
今回のLTでは簡潔に実装できて、GitHubスター数もそこそこあったので python-twitter
というライブラリを用いることにしました。
import twitter api = twitter.Api( consumer_key=CONSUMER_KEY, consumer_secret=CONSUMER_SECRET, access_token_key=ACCESS_TOKEN_KEY, access_token_secret=ACCESS_TOKEN_SECRET ) tweets = api.GetUserTimeline(screen_name='jumpyoshim', count=2)
collectionsのnamedtupleのようなデータ構造で返却されるため、注意が必要です。
IN
[tweet.text for tweet in tweets]
OUT
['RT @akucchan_world: 吉村さんのLTです。\n#pyconjp https://t.co/ZCvHY9ebcw', 'PytestのTDD実践ためになった #pyconjp']
文章のベクトル化
続いて、収集したツイートを数値計算しやすいようにベクトル化します。
ベクトル化の手法として、3つほど確認できました。
https://tifana.ai/words/natural-language-processing/9302.htmltifana.ai
Word2VecやDoc2Vecに関しては、まだ咀嚼しきれない部分があったため、今回はBoWを選択しました。
BoWは、単語の頻出度のみを考慮して、単語の頻出度をベクトル化したものが最も近いデータを推定結果としているだけです。
Word2VecやDoc2Vecは単語の並び順なども考慮するらしく、推定精度が上がるらしいです。まだまだ勉強不足、今後の課題です。
形態素解析
ベクトル化するために、まずは形態素解析をする必要があります。
形態素解析のツールとして、3つほど確認できましたが、環境構築が容易で速度もはやいMeCabを選択してみました。
IN
import MeCab tagger = MeCab.Tagger('mecabrc') data = [] for tweet in tweets: node = tagger.parseToNode(tweet.text) words = [] while node: meta = node.feature.split(',') if meta[0] == '名詞': words.append(node.surface.lower()) node = node.next data.append(words) print(data)
OUT
[['rt', '@', 'akucchan', '_', 'world', ':', '吉村', 'さん', 'lt', '#', 'pyconjp', 'https', '://', 't', '.', 'co', '/', 'zcvhy', '9', 'ebcw'], ['pytest', 'tdd', '実践', 'ため', '#', 'pyconjp']]
※ 形態素解析の際、実際にはURLや@アカウント名、リツイートなどを正規表現で空文字で置換することで、形態素解析された際に意味をなさない単語を排除します。
MeCabとJanomeに関してはpipでインストールできるため利用しやすいですね。
JUMANは環境構築がやや手間ですが、かなり高精度の形態素解析をしてくれるみたいです。
JUMAN - KUROHASHI-CHU-MURAWAKI LAB
特徴ベクトル
形態素解析した単語群は gensim
を用いて辞書を作成し、ベクトル化します。
from gensim import corpora, matutils dictionary = corpora.Dictionary(data) data_train = [] for datum in data: bow = dictionary.doc2bow(datum) dense = list(matutils.corpus2dense([bow], num_terms=len(dictionary)).T[0]) data_train.append(dense) print(data_train)
OUT
[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]]
文書分類器
ここまででデータを揃えることができたので、正解ラベルを用意して学習を行います。
正解ラベルはエゴグラムの診断結果を利用します。Twitter上にエゴグラムの診断結果をツイートするアカウントが多く存在するためです。
以下の23パターンがあります。
- ネクラ厭世タイプ(W型)
- 明朗楽観タイプ(M型)
- 優柔不断タイプ(N型)
- ハイパワータイプ(逆N型)
- 頭でっかちタイプ(逆V型)
- お手あげタイプ(V型)
- 典型的ネクラタイプ(U型)
- ぼんぼんタイプ(逆U型)
- 頑固オヤジタイプ(左上がり型)
- ガキ丸出しタイプ(右上がり型)
- ハイレベルタイプ(オールA型)
- 中庸タイプ(オールB型)
- 原始人タイプ(オールC型)
- ルーズタイプ(CP欠乏型)
- クールタイプ(NP欠乏型)
- 現実無視タイプ(A欠乏型)
- 自閉症タイプ(FC欠乏型)
- 気ままタイプ(AC欠乏型)
- 口うるさタイプ(CP型)
- お人好しタイプ(NP型)
- コンピュータタイプ(A型)
- 自由奔放タイプ(FC型)
- 自己卑下タイプ(AC型)
機械学習
scikit-learn
を利用することで簡単に機械学習ができます。
IN
from sklearn.ensemble import RandomForestClassifier clf = RandomForestClassifier() label_train = ['ネクラ厭世タイプ(W型)', '明朗楽観タイプ(M型)'] clf.fit(data_train, label_train) clf.predict(data_train)
OUT
array(['ネクラ厭世タイプ(W型)', '明朗楽観タイプ(M型)'], dtype='<U12')
学習させたデータを推定してみると、当然同じタイプが推定されることが確認できます。
感想
たとえ数学的な知識に疎くても、gensimやscikit-learnといったライブラリを利用すれば簡単に実現できてしまうのがPythonのすごいところだと感じました。
今後は数学的な知識をより深めたり、機械学習をWebアプリケーションに組み込んだりしてみたいです。今後もPythonを使っていろいろなチャレンジをしていきたいです。
おわりに
今回はPyConJPということでPythonの gensim
や scilkit-learn
などのライブラリを使って文書分類に挑戦してみましたが、Pythonにとらわれなければ他の選択肢が考えられました。
Facebookが開発しているOSSのfastTextや、GoogleのサービスであるGoogle Natural Language API、AWSのサービスであるAmazon Comprehendなどを利用するともっと簡単にテキスト分析ができるかもしれません。
参考文献
以下の記事を大変参考にさせていただきました。深く感謝いたします。
「情熱プログラマー」から学んだこと。
- 作者:Chad Fowler
- 出版社/メーカー: オーム社
- 発売日: 2010/02/26
- メディア: 単行本(ソフトカバー)
概要
- 著作: 「情熱プログラマー」
- 著者: Chad Fowler
- 監訳: でびあんぐる
- 著者経歴:I lead Developer Advocacy at @microsoft and am a venture partner at @blueyard. I also make avant-garde jazz at @chadfowlermusic. It's an acquired taste.
Chad Fowler (@chadfowler) | Twitter
要約
ソフトウェア開発におけるキャリアで根本的に成功を収めるための戦略を提示する
市場の選び方、市場価値の高め方、自分のスキルへの投資方法、周囲へのアピール方法など自分のキャリアに満足感と幸福感を得るための方法を紹介する。
面白かった章とその理由
第4章 マーケティング... スーツ族だけのものじゃない
ビジネスの目的は利益を上げることだ。会社で抜きん出るには、利益を上げるためのビジネスプランに自分がいかに 適合しているかを理解しなきゃならない。
ビジネスの分野における経験は、自分のレパートリーのなかでも重要な部分だと考えるべきだ。
忘れちゃいけない。君の給料はビジネスから生み出されるんだ。
エンジニアにも「ビジネス」という観点が必要なことを学べる章です。
ビジネス視点で仕事ができるエンジニアは実際にはなかなかいないだろうと感じました。
一方で市場的にはそういう考えを持つエンジニアは需要が高いと思うので、意識的に興味を持ってビジネスサイドのことも勉強したいです。
有り余るほどの教育を受けながら期待はずれな働きしかできない同僚と、僕との違い。それは情熱だ。 熱中できるかどうか。
技術に熱中できる + ビジネスへの理解がある = スーパーエンジニア
この方程式が成り立つかどうかはわかりませんが(笑) まずは、今自分がいるO2O業界の理解度からあげる努力をしてみようと思います。
仕事に活かせそうな知識、活かせそうな状況と活かし方
- 1週間に1度自己評価の時間を設ける。
- 積極的に登壇活動する。
- OSSへコントリビュートする。
- 最近数個プルリク出したが、もう少し大きめのOSSに関わりたい。
- Fix typo in Amazon S3 documentation by jumpyoshim · Pull Request #512 · jschneier/django-storages · GitHub
- Define a release process type in Procfile. by jumpyoshim · Pull Request #61 · heroku/python-getting-started · GitHub
- Fix urlpattern for Django 2.0 by jumpyoshim · Pull Request #62 · heroku/python-getting-started · GitHub
- Update Python 2.7.15 and Django 1.11.14 (!2) · Merge Requests · Kamil Trzciński / python-getting-started · GitLab
- 一日の計画を報告する。
- 有言実行し、約束の信頼性を高める。
- 報告できる成果を毎日上げる。
- 21個すべてのCode Kataに挑戦してブログにあげる。
- ビジネスの基本に関する本を1冊手に入れ、最後まで読み通す。
レポート作成方法
@ledsun blog の「新人エンジニアにレポートを書かせて技術書の読み方を伝える。」という記事で紹介されているレポート作成方法を使わせていただきました。
ブクログ始めました
フォローお待ちしてます。
https://booklog.jp/users/jumpyoshi
Django管理画面のカスタマイズ方法【デザイン】
はじめに
Django管理画面のデザイン変更方法を調べてみると3つほど確認できました。
1. style属性を利用する
Django管理画面のテンプレートにHTMLのstyleタグやstyle属性を追加します。
※ 参考:【Django入門】adminサイトの作り方からカスタマイズまで!
少ない変更で簡単にデザインを変更することができますが、この方法は望ましくありません。文書構造とデザインを分離するために、XHTML1.1ではstyle属性は非推奨とされているためです。style属性は将来的に廃止される可能性もあるので利用するのは避けた方が良さそうです。
※ 参考:style属性
2. django/djangoのcssをオーバーライドする
django/djangoの管理画面のスタイルシートをオーバーライドします。
任意のディレクトリにオーバーライドするcssファイルを設置します。このとき、cssのディレクトリ全てをコピーしても良いですし、オーバーライドしたいファイルのみコピーしてきても良いです。
※ 参考:[Python] Django 管理サイトのカスタマイズ(表示面)
こちらは管理画面のデザインを変更する方法として最も一般的であると思いますが、できれば避けたい方法です。Djangoは日々盛んにアップデートされているのでcssも変更されないとはいえません。実際、GitHubのHistoryを確認してみると数ヶ月単位ではありますが、cssもアップデートされています。もしコピーしてきたものとDjangoの本体で差分が発生した場合、追従する必要性が出てくるため、保守が面倒なことになりそうです。
3. Media classを利用する
admin.py
をカスタマイズする方法です。変更したいデザインがモデル固有のものであれば、以下のようにcssやjavascriptを追加することで、その内容を適用することができます。
class MyModelAdmin(admin.ModelAdmin): class Media: js = ('admin/css/myadmin.js',) css = { 'all': ('admin/css/myadmin.css') }
こちらの方法は、Django本体のcssをオーバーライドするわけではないのでメンテナンスが楽です。変更したいデザインがモデル固有のものであれば積極的に採用したい方法です。