# Wikipedia記事分類
## 目的
- コレクションはいわば「ビジネス版wikipedia」
- 現存するwikipedia記事にもビジネス用語を扱ったものはある
→ コレクションに近しいwikipedia記事を引っ張ってきたい
## 準備
### Wikipedia記事DBの作成
参考記事:[【自然言語処理のためのWikipediaデータの扱い方(#1) 】Wikipedia記事DBの作成](https://qiita.com/YuukiMiyoshi/items/aee751a1055144adb18c)
#### Wikipedia本文データをダウンロード
[Wiki dump](https://dumps.wikimedia.org/jawiki/)のサイトからWikipediaの本文データをダウンロード(pages-articleが対象のdumpファイル)
```
wget https://dumps.wikimedia.org/jawiki/20221201/jawiki-20221201-pages-articles.xml.bz2
```
#### wikiextractorをダウンロード
本家をインストールするとエラーが発生するので、有志の方が出している修正版を使用
```
git clone https://github.com/zaemyung/wikiextractor
```
#### Wikiextractorでテキストを整形しつつjsonデータとして抽出
extractedというフォルダ内にAAといったアルファベット2文字のフォルダが作成され、その中に1MB毎に分割された記事データのJsonファイルが作成される
```
./wikiextractor/WikiExtractor.py --json -q -o extracted jawiki-20221201-pages-articles.xml.bz2
```
#### wikiextractor2sqliteをダウンロード
```
git clone https://github.com/yuukimiyo/wikiextractor2sqlite.git
pip install tqdm
```
#### Wikipedia DBを作成
wikiextractor2sqlite.pyを用いて、wikiextractorによる整形結果からsqliteのdbファイルを作成
```
./wikiextractor2sqlite/wikiextractor2sqlite.py ./extracted -o wikipedia.db
```
あらかた終わったらフォルダの整理を行う
#### データベースの確認
Pythonでsqlite3を用いて確認
```
import sqlite3
import pandas as pd
# データベース接続
db_name = "wikipedia.db"
connection_to_db = sqlite3.connect(db_name)
# SQL分を引数に渡すと、Pandas.DataFrameを返す関数
def sql_operation(sql_query, connection):
# SQL文とDBのConnectionをもとにDataFrame作成
df = pd.read_sql(sql_query, connection)
# 出力
return df
# SQL文
query = '''
SELECT * -- 全ての列を指定
FROM extracted_page -- テーブルを指定
'''
# 関数実行
df_db = sql_operation(query, connection_to_db)
df.head(5)
```

`ID, url, title, text`が含まれるDataFrameが返される
### カテゴリーデータベースの作成
参考記事:[【自然言語処理のためのWikipediaデータの扱い方(#2) 】カテゴリーDBの作成](https://qiita.com/YuukiMiyoshi/items/c345a357ac7025515694)
#### 目的
- 各記事はカテゴリーが紐づけされている
- 非ビジネス記事としては「年表」のようなカテゴリに含まれる記事が想定される
→ このような記事のみを抽出したい
#### mysql2sqliteをダウンロード
```
git clone https://github.com/dumblob/mysql2sqlite
```
#### wikipediaのカテゴリー構造データをダウンロード
```
# Wikipediaのdumpページからダウンロード
wget https://dumps.wikimedia.org/jawiki/20221201/jawiki-20221201-categorylinks.sql.gz
# 解凍
gunzip jawiki-20221201-categorylinks.sql.gz
```
#### 記事情報データをダウンロード
```
# Wikipediaのdumpページからダウンロード
wget https://dumps.wikimedia.org/jawiki/20221201/jawiki-20221201-page.sql.gz
# 解凍
gunzip jawiki-20221201-page.sql.gz
```
#### カテゴリー構造データをsqliteのDBへ投入
```
./mysql2sqlite/mysql2sqlite jawiki-20221201-categorylinks.sql | sqlite3 wikicategory.db
```
#### 記事情報データをsqliteのDBへ投入
```
# 対象のキー制約を削除したSQLを新たに作成。
# ("UNIQUE KEY `name_title`"という文字列を検索し、ヒットした行を削除)
sed '/UNIQUE\sKEY\s`name_title`/d' jawiki-20221201-page.sql > jawiki-20221201-page_nouniqkey.sql
# 作成したSQLを使用して記事情報データをDBに投入
./mysql2sqlite/mysql2sqlite jawiki-20221201-page_nouniqkey.sql | sqlite3 wikicategory.db
```
#### データベースの確認
```
import sqlite3
import pandas as pd
# データベース接続
db_name = "wikicategory.db"
connection = sqlite3.connect(db_name)
# SQL文を引数に渡すと、Pandas.DataFrameを返す関数
def sql_operation(sql_query, connection):
# SQL文とDBのConnectionをもとにDataFrame作成
df = pd.read_sql(sql_query, connection)
# 出力
return df
# 表示するカラム
columns = ['page_id','page_title', 'cl_from', 'cl_to']
#特定のカテゴリのサブカテゴリ取得するクエリを返す関数
def f_query(columns, cat):
query = f'''
SELECT {", ".join(columns)}
FROM page AS p JOIN categorylinks AS c ON c.cl_from = p.page_id
WHERE c.cl_type = "subcat" AND c.cl_to = "{cat}";
'''
return query
```

`cl_to`はそのカテゴリないしページがどのカテゴリに属しているかを表す(この場合は年表カテゴリに含まれているものを取得しているので当然`cl_to`は年表になる)
## 分類モデルの構築
### データの準備
#### ビジネス記事・非ビジネス記事の抽出
- アノテーションされたデータを用意する必要がある
- ビジネス記事
- Value Searchのコレクション記事
- 各コレクション名+wikipediaで検索した上位3記事を正解データとして使用
- 今更だけど、かなりノイズがある
- 911記事
- 非ビジネス記事
- 年表, 曖昧さ回避カテゴリに含まれるwikipedia記事
- 桐井さんがアノテーションしてくださったものも学習データに追加
- 501340記事
- 学習の際は、5000記事にダウンサンプリング
- 前処理
- カッコの削除
- カッコ内の情報は非本質的なものが多い印象
- 文字数減らしたい
- 記事の体裁をなしていないデータの除去
- 例:`(名前)とは、`で終わっている
- `タイトルの長さ+5<テキストの長さ`となっている記事だけを抽出
### モデル
- deberta-v3-large+AWP (epoch=7,FOLD=5)
- 結果
- `f1_score = 0.921`
- `fbeta_score(beta=2) = 0.926`
### anotation
- #753
- サービス説明は引かなくていいと思います

- #755
- 技術動向を引いた理由を知りたいです

- #759
- 「~低調だ」の文に市況を引くべきか

- #761
- 事業概要を引けそうで引けない・・?

- #762
- サービス名単体に引く必要はないが、文全体で見るとインテリアであることが分かるので引いてもいいかもしれない

- #764
- 「~問題があった」までは背景に該当する?

- #769
- 出資というよりは事業現況のような気がします

- #773
- 特定の企業(ULA)から見た市場予測なので、市況ではない気がしますが、他のラベルを振るとしたら何でしょうか

- #774
- サービス説明を引いてもよさそう

- #790
- 「健康志向」から背景狙い?
- 文自体サービス説明との違いが分かりにくい

- #801
- 政策という意味で市況にも近いと思ったのですが、ご意見を伺いたいです

- #808
- (↑でも触れたが)「スタートアップ」としか書かれていない箇所にも事業概要を引くべきか
- この他の記事ではだいたい引いてある

- #810
- 「1人客向けの焼肉店「焼肉ライク」」は事業概要?
- #816
- 背景狙いがあってもいいと思いました

- #825
- 背景狙いではなく技術動向の一部のような気もします

- #843
- 市況を引いている理由をお聞きしたいです
- 事業現況と言うよりは事業概要ぽい

- #846
- アノテーション0だったので引いてみました
- #857
- ベンチャー企業
- #862
- 「セミナーを開催」レベルの話は事業現況を引かなくていいと思いますがどうでしょうか
- #866
- 「式典を開いた」には必要か
- #868
- 事業概要?を引いてもよさそう
