Doc2Vec で偏向報道を定量的に評価する 

# 1. 要旨
Doc2Vec の学習済みモデルを使い、文章の「左翼」度、「右翼」度の定量評価を行った。
文章として、「九条の会」の理念と、「一水会」の理念を採用したところ、
「九条の会の理念は左派寄りで、一水会の理念は中間的だが若干右派寄りである」という結果を定量的に得ることに成功した。

これを応用し、報道記事等の角度評価を行うことで、記事がどれだけ左または右に偏っているかを定量的に評価する、つまり偏向報道を定量的に評価することに繋がるだろう。

# 2. 理論

## 2-1. Doc2Vec とは

:::note alert
2-1節は書きかけです。すみません。。。
:::

Doc2Vec は、文章と単語をベクトルに変換する技術である。

## 2-2. Doc2Vec による偏向報道の定量評価
「左翼」、「右翼」の項目が含まれる充分大きな百科事典を Doc2Vec に充分学習させ、 
文章$A$と「左翼」あるいは「右翼」のcos類似度を求めることで、文章$A$がどれだけ左あるいは右に偏っているかを定量評価できるのではないかという試みである。

# 3. 実験

## 3-1. 学習済みモデルの入手

:::note warn
このモデルを利用する場合、 バージョン 3.8.3 等の gensim が必要である。
4.0以降の gensim でモデルを load すると、エラーが出る。
:::

モデルは
https://yag-ays.github.io/project/pretrained_doc2vec_wikipedia/
の dmpv300d を借りた。

モデルのハイパーパラメータは次のとおり。

パラメータ|値
:-:|:-:
ベクトルの次元数|300
ウィンドウサイズ|10
学習率|0.05
エポック数|20

コーパスには 2019/01/14時点での日本語版Wikipedia を用いており、
MeCab により分かち書きが施されているようである。
また、登場回数が2回未満の単語は無視されている。

`jawiki.doc2vec.dmpv300d.model` と 他 3 ファイル(合計4ファイル)をカレントディレクトリに保存する。

## 3-2. 環境の用意

バージョン 3.8.3 の gensim と、MeCab、numpy と matplotlib を pip により環境にインストールしておく。
gensim は新しすぎると、前節のモデルとの互換性がないためエラーになってしまうので要注意。

```
pip install gensim==3.8.3
pip install mecab-python3
pip install numpy
pip install matplotlib
```

## 3-3. 分かち書き関数の定義

文章 $A$ を評価するにあたって、 $A$ を単語単位で区切る(分かち書きする)必要がある。
それを可能にする関数を `tool/tokenize.py` に定義する。

(https://zenn.dev/tokoroteen/articles/ab31ea782df6ec から借りた)

```python:tool/tokenize.py
import MeCab

tagger = MeCab.Tagger("-Owakati")
def tokenize_ja(text):
    node = tagger.parseToNode(text)
    while node:
        if node.feature.split(',')[0] in ["名詞","形容詞","形容動詞","動詞"]:#分かち書きで取得する品詞を指定
            yield node.surface.lower() #単語を出力
        node = node.next

def tokenize(content):
    return [token for token in tokenize_ja(content)]
```

## 3-4. 評価クラスの定義

文章 `angle0` を 0°、文章`angle90` を 90° としたとき、未知の文章 `text` の角度を求めるクラスを定義する。

gensim の Doc2Vec モデル `model` では、
`model.infer_vector(doc_words=`(単語のリストとしての文章)`, steps=`(ステップ回数)`)`
により、未知の文章に対するベクトルを推測することが出来る。

この推測は、本質的に学習と同じことを行うため、結果は毎回揺らぐ。そこで、 `Evaler` オブジェクト `evaler` では、 `evaler.n` 回だけ、推測と角度評価を繰り返し (`evaler.eval_once`メソッド)、その結果の平均値を角度として採用している(`evaler.eval`メソッド)。

```python:evaler.py
from tool.tokenize import tokenize

def cos_sim(v1, v2):
    return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))

class Evaler:
    def __init__(self, model, angle0, angle90):
        """
        angle0: 0°としたい文章のタイトル
        angle90: 90°としたい文章のタイトル
        """
        self.model = model
        try:
            self.model.docvecs[angle0]
            self.model.docvecs[angle90]
        except:
            raise Exception("基準単語がコーパスに含まれていませんでした")
        self.angle0 = angle0
        self.angle90 = angle90

        self.n = 100 # ベクトル推測を行う回数
        self.steps = 20 # ベクトル推測の際のstep数

    def eval_once(self, text, steps):
        text_vec = self.model.infer_vector(doc_words=tokenize(text), steps=steps)
        angle0_vec = self.model.docvecs[self.angle0]
        angle90_vec = self.model.docvecs[self.angle90]

        text_0_sim = cos_sim(text_vec, angle0_vec)
        text_90_sim = cos_sim(text_vec, angle90_vec)
        
        return np.rad2deg(np.arctan2(text_90_sim, text_0_sim))

    def eval(self, text, n=None, steps=None):
        n = n or self.n
        steps = steps or self.steps
        
        results = [self.eval_once(text, steps) for _ in range(n)]

        mean = np.mean(results)
        std  = np.std(results)
        return mean, std, results
```

## 3-5. 評価

「左翼」を0°、「右翼」を90°として、
「九条の会」の「アピール文」と、「一水会」の「基本理念」と「綱領」の角度をそれぞれ計測することにした。

<details><summary>九条の会のアピール文 (http://www.9-jo.jp/appeal.html より)</summary>

> 日本国憲法は、いま、大きな試練にさらされています。
　ヒロシマ・ナガサキの原爆にいたる残虐な兵器によって、五千万を越える人命を奪った第二次世界大戦。この戦争から、世界の市民は、国際紛争の解決のためであっても、武力を使うことを選択肢にすべきではないという教訓を導きだしました。
　侵略戦争をしつづけることで、この戦争に多大な責任を負った日本は、戦争放棄と戦力を持たないことを規定した九条を含む憲法を制定し、こうした世界の市民の意思を実現しようと決心しました。
　しかるに憲法制定から半世紀以上を経たいま、九条を中心に日本国憲法を「改正」しようとする動きが、かつてない規模と強さで台頭しています。その意図は、日本を、アメリカに従って「戦争をする国」に変えるところにあります。そのために、集団的自衛権の容認、自衛隊の海外派兵と武力の行使など、憲法上の拘束を実際上破ってきています。また、非核三原則や武器輸出の禁止などの重要施策を無きものにしようとしています。そして、子どもたちを「戦争をする国」を担う者にするために、教育基本法をも変えようとしています。これは、日本国憲法が実現しようとしてきた、武力によらない紛争解決をめざす国の在り方を根本的に転換し、軍事優先の国家へ向かう道を歩むものです。私たちは、この転換を許すことはできません。
　アメリカのイラク攻撃と占領の泥沼状態は、紛争の武力による解決が、いかに非現実的であるかを、日々明らかにしています。なにより武力の行使は、その国と地域の民衆の生活と幸福を奪うことでしかありません。一九九〇年代以降の地域紛争への大国による軍事介入も、紛争の有効な解決にはつながりませんでした。だからこそ、東南アジアやヨーロッパ等では、紛争を、外交と話し合いによって解決するための、地域的枠組みを作る努力が強められています。
　二〇世紀の教訓をふまえ、二一世紀の進路が問われているいま、あらためて憲法九条を外交の基本にすえることの大切さがはっきりしてきています。相手国が歓迎しない自衛隊の派兵を「国際貢献」などと言うのは、思い上がりでしかありません。
　憲法九条に基づき、アジアをはじめとする諸国民との友好と協力関係を発展させ、アメリカとの軍事同盟だけを優先する外交を転換し、世界の歴史の流れに、自主性を発揮して現実的にかかわっていくことが求められています。憲法九条をもつこの国だからこそ、相手国の立場を尊重した、平和的外交と、経済、文化、科学技術などの面からの協力ができるのです。
　私たちは、平和を求める世界の市民と手をつなぐために、あらためて憲法九条を激動する世界に輝かせたいと考えます。そのためには、この国の主権者である国民一人ひとりが、九条を持つ日本国憲法を、自分のものとして選び直し、日々行使していくことが必要です。それは、国の未来の在り方に対する、主権者の責任です。日本と世界の平和な未来のために、日本国憲法を守るという一点で手をつなぎ、「改憲」のくわだてを阻むため、一人ひとりができる、あらゆる努力を、いますぐ始めることを訴えます。
</details>


<details><summary>一水会の基本理念+綱領 (http://www.issuikai.jp/issuikai.html より)</summary>

>　わが一水会は、昭和45年11月25日「楯の会事件」での三島由紀夫・森田必勝両烈士の自裁を“戦後体制打破”へ向けた果敢な行動と位置づけ、両烈士らの魂魄を継承するため、昭和47年5月30日、「保守の拠点か、変革の原基か」という思想的命題を掲げ結成した。当初の結成宣言は以下の通りである。
>
>　 維新を永久的浪漫対象とする吾人等は、「維新を阻害し停滞させる諸体制諸権力と対立し、それを打破すべく行動する」』という立場を明確にし、変革者としての矜持を持ち尊皇義軍の精神による平成維新、世界平和に向けて、戦いの陣形を築くことを内外に宣言した。
>
>　結成から今日まで四十数年が経っているが、これまでの戦いの中で基本的原則は一切不変であり、今日においても生成発展を遂げるべく、より高いレベルで政治理念をより集約化させ、対米自立、自主憲法制定、日米安保破棄、戦後体制打破を目指して、維新成就のために闘っている。
>
>　我々は日本の完全なる独立と、敗戦によって失われた日本国の誇りと民族の尊厳を恢復するため、我が国の歴史・伝統・文化を基調に戦後民主主義の誤りをただし、道義的国民共同体を創造する。
>　また、日本のみならず、世界のあらゆる民族を尊重し、戦勝国を中心とした現在の国連に対抗する新たなる国際組織と世界新秩序の樹立に向けて邁進する。
　この趣旨の実現に向け、我々は自省心のある社会運動を実践し、維新変革の達成を期す。


</details>



```python
from gensim.models.doc2vec import Doc2Vec
from evaler import Evaler
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = "MS Gothic"



model = Doc2Vec.load("jawiki.doc2vec.dmpv300d.model")

九条の会アピール = """
日本国憲法は、いま、大きな試練にさらされています。
　ヒロシマ・ナガサキの原爆にいたる残虐な兵器によって、五千万を越える人命を奪った第二次世界大戦。この戦争から、世界の市民は、国際紛争の解決のためであっても、武力を使うことを選択肢にすべきではないという教訓を導きだしました。
　侵略戦争をしつづけることで、この戦争に多大な責任を負った日本は、戦争放棄と戦力を持たないことを規定した九条を含む憲法を制定し、こうした世界の市民の意思を実現しようと決心しました。
　しかるに憲法制定から半世紀以上を経たいま、九条を中心に日本国憲法を「改正」しようとする動きが、かつてない規模と強さで台頭しています。その意図は、日本を、アメリカに従って「戦争をする国」に変えるところにあります。そのために、集団的自衛権の容認、自衛隊の海外派兵と武力の行使など、憲法上の拘束を実際上破ってきています。また、非核三原則や武器輸出の禁止などの重要施策を無きものにしようとしています。そして、子どもたちを「戦争をする国」を担う者にするために、教育基本法をも変えようとしています。これは、日本国憲法が実現しようとしてきた、武力によらない紛争解決をめざす国の在り方を根本的に転換し、軍事優先の国家へ向かう道を歩むものです。私たちは、この転換を許すことはできません。
　アメリカのイラク攻撃と占領の泥沼状態は、紛争の武力による解決が、いかに非現実的であるかを、日々明らかにしています。なにより武力の行使は、その国と地域の民衆の生活と幸福を奪うことでしかありません。一九九〇年代以降の地域紛争への大国による軍事介入も、紛争の有効な解決にはつながりませんでした。だからこそ、東南アジアやヨーロッパ等では、紛争を、外交と話し合いによって解決するための、地域的枠組みを作る努力が強められています。
　二〇世紀の教訓をふまえ、二一世紀の進路が問われているいま、あらためて憲法九条を外交の基本にすえることの大切さがはっきりしてきています。相手国が歓迎しない自衛隊の派兵を「国際貢献」などと言うのは、思い上がりでしかありません。
　憲法九条に基づき、アジアをはじめとする諸国民との友好と協力関係を発展させ、アメリカとの軍事同盟だけを優先する外交を転換し、世界の歴史の流れに、自主性を発揮して現実的にかかわっていくことが求められています。憲法九条をもつこの国だからこそ、相手国の立場を尊重した、平和的外交と、経済、文化、科学技術などの面からの協力ができるのです。
　私たちは、平和を求める世界の市民と手をつなぐために、あらためて憲法九条を激動する世界に輝かせたいと考えます。そのためには、この国の主権者である国民一人ひとりが、九条を持つ日本国憲法を、自分のものとして選び直し、日々行使していくことが必要です。それは、国の未来の在り方に対する、主権者の責任です。日本と世界の平和な未来のために、日本国憲法を守るという一点で手をつなぎ、「改憲」のくわだてを阻むため、一人ひとりができる、あらゆる努力を、いますぐ始めることを訴えます。
"""

一水会基本理念と綱領 = """
　わが一水会は、昭和45年11月25日「楯の会事件」での三島由紀夫・森田必勝両烈士の自裁を“戦後体制打破”へ向けた果敢な行動と位置づけ、両烈士らの魂魄を継承するため、昭和47年5月30日、「保守の拠点か、変革の原基か」という思想的命題を掲げ結成した。当初の結成宣言は以下の通りである。

　 維新を永久的浪漫対象とする吾人等は、「維新を阻害し停滞させる諸体制諸権力と対立し、それを打破すべく行動する」』という立場を明確にし、変革者としての矜持を持ち尊皇義軍の精神による平成維新、世界平和に向けて、戦いの陣形を築くことを内外に宣言した。

　結成から今日まで四十数年が経っているが、これまでの戦いの中で基本的原則は一切不変であり、今日においても生成発展を遂げるべく、より高いレベルで政治理念をより集約化させ、対米自立、自主憲法制定、日米安保破棄、戦後体制打破を目指して、維新成就のために闘っている。

　我々は日本の完全なる独立と、敗戦によって失われた日本国の誇りと民族の尊厳を恢復するため、我が国の歴史・伝統・文化を基調に戦後民主主義の誤りをただし、道義的国民共同体を創造する。
　また、日本のみならず、世界のあらゆる民族を尊重し、戦勝国を中心とした現在の国連に対抗する新たなる国際組織と世界新秩序の樹立に向けて邁進する。
　この趣旨の実現に向け、我々は自省心のある社会運動を実践し、維新変革の達成を期す。
"""


evaler = Evaler(model, "左翼", "右翼")
evaler.n = 1000
evaler.steps = 100

mean, std, results9 = evaler.eval(九条の会アピール)
print("九条の会: 平均", mean, "標準偏差", std)

mean, std, results1 = evaler.eval(一水会基本理念と綱領)
print("一水会: 平均", mean, "標準偏差", std)


# 図の作成
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# 最初のヒストグラム
axes[0].hist(results9, bins=30)
axes[0].set_title('九条の会')

# 二つ目のヒストグラム
axes[1].hist(results1, bins=30)
axes[1].set_title('一水会')

# 図の表示
plt.tight_layout()
plt.show()
    

```


# 4. 結果

次の結果を得た。

```
九条の会: 平均 34.50507 標準偏差 1.4612975
一水会: 平均 47.105156 標準偏差 1.0382406
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319477/3513cfb7-09d2-359a-b678-81ecd5a70e7a.png)

左翼を0°、右翼を90°としたとき、九条の会の理念は 約34.5°、一水会の理念は 約47.1° と計算された。 九条の会が左寄りで、一水会が若干右寄りとなったこの結果は、直感にもおおよそ一致しているだろう。

# 5. まとめ
今回は、文章がどれだけ左寄り/右寄りかを、角度という数値で表すことに成功した。
これを応用し、報道記事等の角度評価を行うことで、偏向報道を定量的に評価することに繋がるのではないかと考える。