どん底から這い上がるまでの記録

どん底から這い上がりたいけど這い上がれない人がいろいろ書くブログ(主にプログラミング)

ロシアW杯 日本代表について雑談ができる対話エージェントを作る(データ収集編)①

Twitterでは日々幅広い話題に関するやり取りが行われています。

今回、日本代表の試合が行われた日の対話データを手に入れることができたので、このデータを使って日本代表についてのみ雑談ができる対話エージェントを作ってみます。

この記事ではどうやってデータを収集したのかを書いていきます。

環境

MeCabWindowsにインストールするには

https://www.pytry3g.com/entry/2018/04/24/143934#Windows

データを集める

今回、Twitterの対話データを集めるにあたって、こちらをー>(GitHub - higepon/twitter_conversation_crawler: Twitter Conversation Crawler)使わせて頂きました。

TwitterAPIを利用するので、Twitter Application Managementでconsumer_key, consumer_secret, access_token, access_token_secretを取得します。これらの詳細について今回は割愛します。一応説明しているリンクを載せておきます。->(http://www.nltk.org/howto/twitter.html)英語で書かれていますが……

 

APIキーを用意し設定した後、crawler.pyを実行するとツイートを集めることができます。

データの前処理

crawler.pyで日本代表の試合が行われた6/19, 24, 28, 7/2のツイートを集めました。その後、textify.pyを使って対話データに成形しました。その際にURLやハッシュタグを含む対話データは取り除くようにします。

手に入れた対話データは以下のような3つのツイートから構成されています。

  •    ユーザAによるツイート -(1)
  • (1)に対するユーザBのリプライ -(2)
  • (2)に対するユーザAのリプライ -(3)

手に入れた対話データのほとんどはワールドカップとは関係のないものです

そのため、ワールドカップに関するキーワードを含むツイートを探してきます。今回はワールドカップに関するキーワードが2つ以上のツイートに含まれていた場合、それらを対話データとして使うようにします。

そのために、textify.pyを少しいじります。

__init__の変更

import MeCab
import argparse
import re
import sqlite3
import sys


# class to dump conversation as text from db.
class Dumper:
    def __init__(self, db):
        self.db = db
        self.url_regexp = re.compile(r"https?://")
        self.name_regexp = re.compile(r"@([A-Za-z0-9_]+)")
        self.tag_regexp = re.compile(r"#(\w+)") #ハッシュタグを取り除く
        self.cnt = 0 #対話データをカウントする
        self.tagger = MeCab.Tagger("-Owakati") #分かち書き
        # キーワードの設定
        self.keyword = ["本田", "香川", "川島", "大迫", "長友", "長谷部", "乾", "原口",
                        "昌子", "酒井", "柴崎", "西野", "ワールドカップ",
                        "日本", "コロンビア", "セネガル", "ポーランド", "ベルギー"]

is_valid_conversation

ハッシュタグを取り除くところを追加

    def is_valid_conversation(self, text1, text2, text3):
        if text1 is None or text2 is None or text3 is None:
            return False
        # URLを含むツイートは取り除く
        for text in [text1, text2, text3]:
            if re.search(self.url_regexp, text):
                return False
        # ハッシュタグを含むツイートは取り除く
        for text in [text1, text2, text3]:
            if re.search(self.tag_regexp, text):
                return False

        return True

dump

キーワードを含むかどうかを調べるところを追加。

    def dump(self):
        conn = sqlite3.connect(self.db)
        cursor = conn.cursor()

        cursor.execute(
            "select count(*) from conversation")
        total_conversation = cursor.fetchall()[0][0]

        cursor.execute(
            "select sid1, sid2, sid3 from conversation")
        for row in cursor:
            sid1, sid2, sid3 = row
            text1 = self.tweet_text(conn, sid1)
            text2 = self.tweet_text(conn, sid2)
            text3 = self.tweet_text(conn, sid3)
            if self.is_valid_conversation(text1, text2, text3):
                text1, text2, text3 = self.mapper(text1, text2, text3)

                # キーワードを含むか調べる
                if self.is_valid_statement(text1, text2, text3):
                    self.cnt += 1

        conn.close()
        print("Number of total conversation: {}".format(total_conversation))
        print("Number of valid conversation related to World Cup: {}".format(self.cnt))

mapperの変更

    def mapper(self, text1, text2, text3):
        text1 = text1.replace("&gt;", ">").replace("&lt;", "<")
        text2 = text2.replace("&gt;", ">").replace("&lt;", "<")
        text3 = text3.replace("&gt;", ">").replace("&lt;", "<")
        #text2 = re.sub(self.name_regexp, '@john', text2)
        text2 = re.sub(self.name_regexp, '', text2)[1:]
        #text3 = re.sub(self.name_regexp, '@paul', text3)
        text3 = re.sub(self.name_regexp, '', text3)[1:]
        return text1, text2, text3

is_valid_statement

新しく追加。

ワールドカップに関するキーワードが2つ以上のツイートに含まれる場合Trueを返す。

    def tokenizer(self, text):
        return self.tagger.parse(text).strip()

    def is_valid_statement(self, text1, text2, text3):
        text1 = self.tokenizer(text1)
        text2 = self.tokenizer(text2)
        text3 = self.tokenizer(text3)
        flags = [0, 0, 0]
        for word in self.keyword:
            if word in text1.split():
                flags[0] = 1
            elif word in text2.split():
                flags[1] = 1
            elif word in text3.split():
                flags[2] = 1
        #return any(flags)
        return 1 if sum(flags) >= 2 else 0

前処理の結果

3つのツイートから構成する対話データを1としてカウントします。

6/19 日本xコロンビア

手に入れた対話データは全部で11923。

前処理をすると、92。

6/24 日本xセネガル

手に入れた対話データは全部で13672。

前処理をすると、62。

6/28 日本xポーランド

手に入れた対話データは全部で12679。

前処理をすると、122。

7/2 日本xベルギー

手に入れた対話データは全部で8841。

前処理をすると、55。

サンプル

手に入れた対話データのサンプル

ユーザA:セネガルつええ、ボルト三体くらいいるわ笑笑
ユーザB:しょーみコロンビアより強い
ユーザA:それなまちがいないわ

続き

次回、PyTorchを使って対話エージェントを作る予定。