はじめに
- 文書分類をしたくなりました
- pythonの練習も兼ねて、pythonで実装することにしました
前提
- Windows 10 pro バージョン1803
- Windows Subsystem for Linux(WSL)版ubuntu バージョン8.04 LTS (Bionic Beaver)
全体の流れ
- linuxを用意する
- pythonを入れる
- 日本語コーパスを手に入れる
- 日本語パーサーを入れる
- 分類ライブラリを入れる
- 教師データを作る
- モデルを作る
- 分類する
Windows Subsystem for Linux(WSL)でubuntuを入れる
- こちらの記事を参照のこと
Windows Subsystem for Linuxにssh接続する
- こちらの記事を参照のこと
- 以下、基本的にはteratermで作業
viを初心者でも使いやすくする
- こちらの記事を参照のこと
- 初心者なりに、以下、ソースはvimでがりがり書いていきます
gitに最低限の設定をする
- gitはバージョンによっては最低限の設定をしないとgit clone出来ないので最低限の設定をする
git config --global user.name "First-name Family-name"
git config --global user.email "username@example.com"
- gitでコミットした時に起動するエディタがnanoなのは初心者には不便なので、vimにする
- ソースを書くときは出来る限りコミットは細かくして、コミット理由も日本語で良いので書いた方がいい
- 後で楽が出来ます
git config --global core.editor 'vim -c "set fenc=utf-8"'
- ついでに、色も付けておく
- 不要なら設定しなくても良い
git config --global color.diff auto
git config --global color.status auto
pythonを入れる
- Anacondaのページに行って、linux版の最新版のダウンロードurlを「リンクのアドレスをコピー」で取得
- あとは、wgetでファイルを取得してインストールコマンドを入力
wget https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh
bash Anaconda3-5.2.0-Linux-x86_64.sh
- 上記のurlは記事作成時点の最新なので、適宜修正する
- 最初はライセンスが表示されるので、スペースで読み進める
- ライセンスに同意するか聞かれるので同意する
Do you accept the license terms? [yes|no]
[no] >>> yes
- インストール場所を聞かれるので、特にこだわりがなければエンターで進める
- Press ENTER to confirm the location
- Press CTRL-C to abort the installation
- Or specify a different location below
[/home/hoge/anaconda3] >>>
- 環境変数にAnaconda3のパスをいれるか聞かれるので、好みによって、yesを入力する
- 迂闊にyesにすると、curlがAnaconda環境のものを優先使用するようになったりするので、各自の判断でどうぞ
- noを選んでも、「export PATH=(アナコンダをインストールしたパス)/anaconda3/bin:$PATH」でいつでも使用できるので特に気にしない
- なんなら、あとで、「vi ~/.bashrc」して末尾に、「export PATH=(アナコンダをインストールしたパス)/anaconda3/bin:$PATH」加えて、「source ~/.bashrc」しても同じ
Do you wish the installer to prepend the Anaconda3 install location
to PATH in your /home/ubuntu/.bashrc ? [yes|no]
[no] >>> yes
- Microsoft VSCodeをインストールするか聞かれるので、不要ならnoを入力する
- vimで編集していくつもりなので、ここではno
Do you wish to proceed with the installation of Microsoft VSCode? [yes|no]
>>> no
- 編集した.bashrcを有効にする
source ~/.bashrc
日本語コーパスの取得
- ロンウイット様が、livedoor ニュースのクリエイティブ・コモンズライセンスが適用されるニュース記事のデータを公開してくださっているのでそれを使う
- 上記ページで「収集時期:2012年9月上旬 ダウンロード(通常テキスト):ldcc-20140209.tar.gz ダウンロード」と書いてあるリンクのダウンロードurlを「リンクのアドレスをコピー」で取得
- 上記urlをwgetして、展開する
wget https://www.rondhuit.com/download/ldcc-20140209.tar.gz
tar -zxvf ldcc-20140209.tar.gz
日本語パーサーを入れる
- 今回はMeCabを使う
- コマンドライン版も入れたけど、もしかしたら、不要かも
- git cloneして、makeしてインストールする
git clone https://github.com/taku910/mecab.git
cd mecab/mecab
./configure --enable-utf8-only
make
make check
sudo make install
- 辞書もmakeして、インストールする
cd ../mecab-ipadic
./configure --with-charset=utf8
make
sudo make install
- もしかしたら、ここまで不要かも
- 以下だけでいいという話を聞いたので、上記までは無視してよいかも
pip install mecab-python3
- 上記だけで済むならそれに越したことはない
- 念のため、サンプルスクリプトで、日本語のパーシングが出来ることを確認しておく
mecab_test.py
import MeCab
def get_token(content):
tokens = []
tagger = MeCab.Tagger('')
tagger.parse('')
node = tagger.parseToNode(content)
while node:
tokens.append(node.surface)
node = node.next
return tokens
def main():
content="これはテストコーパスです。これをうまく分割できるかな?"
print(get_token(content))
if __name__ == '__main__':
main()
- tagger.parse('')は、やらないと動かない既知の不良を避けるバッドノウハウ
- スクリプトを実行する
python mecab_test.py
- 以下のように出力されていたらOK
['', 'これ', 'は', 'テスト', 'コーパス', 'です', '。', 'これ', 'を', 'うまく', '分割', 'できる', 'か', 'な', '?', '']
分類ライブラリを入れる
- 今回はFastTextを使う
- git cloneして、makeしてインストールする
git clone https://github.com/facebookresearch/fastText.git
cd fastText/
make
- makeすると以下のようなメッセージが出るはず
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/args.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/dictionary.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/productquantizer.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/matrix.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/qmatrix.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/vector.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/model.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/utils.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/fasttext.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops args.o dictionary.o productquantizer.o matrix.o qmatrix.o vector.o model.o utils.o fasttext.o src/main.cc -o fasttext
- エラーが出たりしなければ、pipでインストール
pip install fasttext
教師データを作る
- 上で取得したlivedoorニュースのデータから、教師データを作る
ファイル一覧を持っておく
- 以下の処理で楽をするために、ファイル一覧を持っておく
- そのためのファイル一覧作成スクリプトを作る
make_file_list.py
import os
import sys
def print_list(list):
for item in list:
print(item)
def get_files(path,file_list):
for file in os.listdir(path):
full_path = path + file
if os.path.isfile(full_path):
file_list.append(full_path)
elif os.path.isdir(full_path):
get_files(full_path + "/",file_list)
def main(argv):
path = argv[0]
file_list = []
get_files(path,file_list)
print_list(file_list)
if __name__ == '__main__':
main(sys.argv[1:])
- 日本語コーパスを置いた場所を指定して、標準出力をファイルに吐きだす
- 引数はパスで、そこから再起的にサブディレクトリ内のファイルも出力する
- パスは環境に合わせて修正すること
python make_file_list.py /home/hoge/text/ > all_file_list.txt
分野ごと教師データの元を選ぶ
- 教師データのもとをいれるディレクトリを決める
- 上記ディレクトリを掘っておく
- Politics、Economy、Societyの分類にする予定なので、それも掘っておく
- パスは環境に合わせて修正すること
mkdir -p /home/hoge/text_category/Politics
mkdir /home/hoge/text_category/Economy
mkdir /home/hoge/text_category/Society
- 日本語コーパスの中からキーワードマッチングして、一致したものを、先ほど掘ったディレクトリに格納するスクリプトを書く
- 二重持ちになるけど気にしない
- キーワードは産経新聞記事分類を参考にした
- カテゴリーが3個だけなのは、キーワードを作るのが面倒くさかったから
make_categorize_text.py
import sys
def get_content(file_name):
contexts = []
with open(file_name, 'r', encoding='utf-8') as file:
line = file.readline()
while line:
contexts.append(line.strip())
line = file.readline()
return ''.join(contexts)
def put_content(file_name,content):
with open(file_name, 'w', encoding='utf-8') as f:
f.write(content)
def make_categorized_data(file_list, text_path):
keyword_dict = {
'Politics':['政治','国会','選挙','政党','行政','司法','警察','財政','外交','在日外国人','旧日本領土','軍事'],
'Economy':['経済','金融','株式','貿易','為替','産業','企業','農林','水産','鉱業','工業','運輸','通信','土木','建築','商業'],
'Society':['社会','厚生','医事','衛生','公害','地球','環境','生活','料理','住生活','婦人','子供','青少年','趣味','娯楽','観光','旅行','行事','祝祭','世相','風俗'],
}
file_num = {
'Politics':'0',
'Economy':'0',
'Society':'0',
}
for file_name in file_list:
content = get_content(file_name)
flag = -1
for category in keyword_dict.keys():
for keyword in keyword_dict[category]:
flag = content.find(keyword)
if flag > -1:
break
if flag > -1:
full_path_file_name = text_path+category+'/'+category+file_num[category]
put_content(full_path_file_name,content)
file_num[category] = str( int(file_num[category]) + 1 )
def get_file_list(file_name):
file_list = []
with open(file_name, 'r', encoding='utf-8') as file:
line = file.readline()
while line:
file_list.append(line.strip())
line = file.readline()
return file_list
def main(argv):
file_name = argv[0]
text_path = argv[1]
file_list = get_file_list(file_name)
make_categorized_data(file_list, text_path)
if __name__ == '__main__':
main(sys.argv[1:])
- 教師データのもとになるデータを作る
python make_categorize_text.py all_file_list.txt /home/hoge/categorized_text/
- 教師データのもとになるデータのリストを作る
python make_file_list.py /home/hoge/categorized_text/ > categorized_file_list.txt
教師データを作る
- 教師データは、以下のような構造になっている
__label__0 「 三浦 春 馬 」 さん と ドライブ に 行き たい 1 月 17 日 に スタート し た 、 三浦 春 馬 さん …
__label__0 “ 神社 コンシェルジュ ” が 選ぶ 、 恋愛 成就 を 祈願 し て 、 美人 証明 を 受ける …
:
__label__1 ・ 解説 - 怪物 と の 戦い 、 その ピーク - ドラマ 『 クリミナル・マインド / FBI vs . 異常 犯罪 』…
:
- 先頭に
__label__(数字)
で、あとは分かち書きされたテキスト列になっている - 分かち書きには、日本語パーサとして入れたMeCabを使用する
- labelと分類の対応辞書もついでに作る
make_training_data.py
import MeCab
import os
import re
import sys
def get_content(file_name):
contexts = []
with open(file_name, 'r', encoding='utf-8') as file:
line = file.readline()
while line:
contexts.append(line.strip())
line = file.readline()
return ''.join(contexts)
def get_token(content):
tokens = []
tagger = MeCab.Tagger('')
tagger.parse('')
node = tagger.parseToNode(content)
while node:
tokens.append(node.surface)
node = node.next
return tokens
def get_file_name(path):
return os.path.basename(path)
def get_label(path,label_dict):
file_name = get_file_name(path)
name, ext = os.path.splitext(file_name)
category_name = re.sub(r'[0-9]+','',name)
if category_name in label_dict.keys():
label = label_dict[category_name];
else:
label = label_dict['category_number']
label_dict[category_name] = label
label_dict['category_number'] = str( int(label) + 1)
return str(label)
def make_training_data(file_list,label_dict):
for file_name in file_list:
print_training_data(file_name,label_dict)
def format_content(content):
content = re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-…]+', "", content)
return content
def print_training_data(path,label_dict):
content = get_content(path)
content = format_content(content)
tokens = get_token(content)
text = ' '.join(tokens)
label = get_label(path,label_dict)
print('__label__'+label+' '+text)
def get_file_list(file_name):
file_list = []
with open(file_name, 'r', encoding='utf-8') as file:
line = file.readline()
while line:
file_list.append(line.strip())
line = file.readline()
return file_list
def output_dict(file_name, label_dict):
with open(file_name, mode='w', encoding='utf-8') as file:
for key, value in label_dict.items():
file.write(key+':'+value+'\n')
def main(argv):
#file_name = ""
#dict_name = ""
file_name = argv[0]
dict_name = argv[1]
label_dict = {'category_number':'0'}
file_list = get_file_list(file_name)
make_training_data(file_list,label_dict)
output_dict(dict_name, label_dict)
if __name__ == '__main__':
main(sys.argv[1:])
- 教師データのもとになるデータのリストとラベルの辞書名を指定して、標準出力をファイルに吐きだす
- 引数は、第一引数が教師データのもとになるデータのリストのファイル、第二引数がラベルの辞書名
- パスは環境に合わせて修正すること
python make_training_data.py categorized_file_list.txt dictiory > training_data.txt
モデルを作る
- fasttextの機能でサクッとモデルを作成
make_model.py
import fasttext as ft
import sys
def main(argv):
input_file = argv[0]
output_file = argv[1]
ft.supervised(input_file, output_file, label_prefix='__label__', thread=8)
if __name__ == '__main__':
main(sys.argv[1:])
- 引数は、第一引数が教師データ、第二引数が出力するモデル名
- ファイル名は環境に合わせて修正すること
python make_model.py training_data.txt model
分類する
- おまちかねの分類タイム
コマンドラインから入力した文章を分類する
- 引数に直接文字列を渡し、その文字列を分類してみる
fasttext_check.py
import fasttext as ft
import MeCab
import sys
def get_score(result,label_dict):
scores = []
for item in result:
scores.append(label_dict[item[0]]+':'+str(item[1]))
return scores
def get_label_dict(dict_name):
dictionay = {}
with open(dict_name, 'r', encoding='utf-8') as f:
line = f.readline()
while line:
category_name, category_number = line.split(':')
dictionay['__label__'+category_number.strip()] = category_name
line = f.readline()
return dictionay
def get_token(content):
tokens = []
tagger = MeCab.Tagger('')
tagger.parse('')
node = tagger.parseToNode(content)
while node:
tokens.append(node.surface)
node = node.next
return tokens
def main(argv):
model_name = argv[0]
dict_name = argv[1]
content = argv[2]
label_dict = get_label_dict(dict_name)
classifier = ft.load_model(model_name)
tokens = get_token(content)
estimate = classifier.predict_proba([' '.join(tokens)], k=3)
scores = get_score(estimate[0],label_dict)
print(file_name, scores)
if __name__ == '__main__':
main(sys.argv[1:])
- 第一引数にモデル名、第二引数に辞書名、第三引数に分類したい文字列を入れる
- モデル名は、指定したモデル名の後ろに拡張子.binが付くので注意
python fasttext_check.py model.bin dictiory 自民党の党・政治制度改革実行本部(塩崎恭久本部長)は13日、党本部で総会を開き、党改革に関する提言案をまとめた。
- 結果は以下の通り
['Society:0.529297', 'Economy:0.361328', 'Politics:0.105469']
- あかん。Politicsのつもりだったけど、一番低い
- 次、経済っぽい文字列
python fasttext_check.py model.bin dictiory パウエル議長は12日、ラジオ局アメリカン・パブリック・メディアの番組でインタビューに応じ、「米経済は非常に良好」で失業率が近年まれに見る低水準にあり、インフレ率は当局の目標とする2%に近いと述べた。
- こちらも、あかん感じ
- Politicsは下がったけど、Economyも下がって、Societyが上がっている始末
['Society:0.585938', 'Economy:0.34375', 'Politics:0.0664063']
- 最後に、社会っぽい文字列も入れてみる
python fasttext_check.py model.bin dictiory 人生100年時代とも言われるこれからの時代においては、技術の進展に伴う産業構造の変化や、長寿命化社会の到来など、大きな転換に直面することになる。こうした時代においては、新たなステージで求められる能力・スキルを身に付けながら、個人が主体的に人生を再設計できるよう、経済社会環境の変化に対応した社会人の学び(リカレント教育)を推進することが重要である。
- まぁ、Societyが上がって、EconomyとPoliticsは下がってる
- と、いえなくもないかな
['Society:0.609375', 'Economy:0.333984', 'Politics:0.0527344']
ファイル一覧を渡してまとめて分類する
- 日本語コーパスを全てぶち込んでみる
fasttext_test.py
import fasttext as ft
import MeCab
import sys
def get_score(result,label_dict):
scores = []
for item in result:
scores.append(label_dict[item[0]]+':'+str(item[1]))
return scores
def get_label_dict(dict_name):
dictionay = {}
with open(dict_name, 'r', encoding='utf-8') as f:
line = f.readline()
while line:
category_name, category_number = line.split(':')
dictionay['__label__'+category_number.strip()] = category_name
line = f.readline()
return dictionay
def get_content(file_name):
contexts = []
with open(file_name, 'r', encoding='utf-8') as f:
line = f.readline()
while line:
contexts.append(line.strip())
line = f.readline()
return ''.join(contexts)
def get_token(content):
tokens = []
tagger = MeCab.Tagger('')
tagger.parse('')
node = tagger.parseToNode(content)
while node:
tokens.append(node.surface)
node = node.next
return tokens
def get_file_list(file_name):
file_list = []
with open(file_name, 'r', encoding='utf-8') as f:
line = f.readline()
while line:
file_list.append(line.strip())
line = f.readline()
return file_list
def main(argv):
model_name = argv[0]
dict_name = argv[1]
test_data = argv[2]
label_dict = get_label_dict(dict_name)
classifier = ft.load_model(model_name)
file_list = get_file_list(test_data)
for file_name in file_list:
content = get_content(file_name)
tokens = get_token(content)
estimate = classifier.predict_proba([' '.join(tokens)], k=3)
scores = get_score(estimate[0],label_dict)
print(file_name, scores)
if __name__ == '__main__':
main(sys.argv[1:])
- 第一引数にモデル名、第二引数にラベル辞書名、第三引数にファイル一覧ファイルを渡す
- 結果は標準出力なので、ファイルで受ける
python fasttext_test.py model.bin dictiory all_file_list.txt > result.txt
- 分類結果を見てみる
- 分類順はSociety > Economy > Politicsがずらりと並んでいた
result.txt
/home/hoge/text/peachy/peachy-6731010.txt ['Society:0.625', 'Economy:0.326172', 'Politics:0.0449219']
:
/home/hoge/text/smax/smax-6913983.txt ['Society:0.507812', 'Economy:0.367188', 'Politics:0.121094']
:
/home/hoge/text/sports-watch/sports-watch-4604621.txt ['Society:0.582031', 'Economy:0.34375', 'Politics:0.0703125']
:
- なんか全部、Societyに一番近いことになってしまった。
- 教師データの作り方があかんかった気がする
- 教師データの元になるデータを見てみたが、どの分類も似たような文書が渡されてしまっていたようだった
- キーワードで絞り込んで教師データの元になるデータを作るのは無理があったようだ
考察
- 教師データの元となるデータの数を調べてみた
ls /home/hoge/text_category/Politics/ | wc
320 320 3730
ls /home/hoge/text_category/Economy/ | wc
1561 1561 17622
ls /home/hoge/text_category/Society/ | wc
2518 2518 29106
- 10倍近く差があった
- これが悪影響を与えた可能性がある
改善案1
- とりあえず、教師データを300個づつに制限してみる
- categorized_file_list.txtを加工すればよい
- viで開いて、「/Politics」に飛んで「20dd」で20行削除
- 「/Economy」に飛んで「1261dd」で1261行削除
- 「/Society」に飛んで「2218dd」で2218行削除
- 確認する
grep Society categorizd_file_list2.txt | wc
300 300 16805
grep Economy categorized_file_list2.txt | wc
300 300 16770
grep Politics categorized_file_list2.txt | wc
300 300 17292
- いい感じ
- あとは同じ
- 折角だからファイル名などはあとで比較できるように、変えた
python make_training_data.py categorized_file_list2.txt dictiory2 > training_data2.txt
python make_model.py training_data2.txt model2
- モデルを作ったので、チェックする
python fasttext_check.py model2.bin dictiory2 自民党の党・政治制度改革実行本部(塩崎恭久本部長)は13日、党本部で総会を開き、党改革に関する提言案をまとめた。
['Politics:0.332031', 'Economy:0.332031', 'Society:0.332031']
python fasttext_check.py model2.bin dictiory2 パウエル議長は12日、ラジオ局アメリカン・パブリック・メディアの番 組でインタビューに応じ、「米経済は非常に良好」で失業率が近年まれに見る低水準にあり、インフレ率は当局の目標とする2%に近いと述べた。
['Politics:0.332031', 'Economy:0.332031', 'Society:0.332031']
python fasttext_check.py model2.bin dictiory2 人生100年時代とも言われるこれからの時代においては、技術の進展に伴う産業構造の変化や、長寿命化社会の到来など、大きな転換に直面することになる。こうした時代においては、新たなステージで求められる能力・スキルを身に付けながら、 個人が主体的に人生を再設計できるよう、経済社会環境の変化に対応した社会人の学び(リカレント教育)を推進することが重要である。
['Politics:0.332031', 'Economy:0.332031', 'Society:0.332031']
- 悪化している
- 全てのカテゴリの評価値が0.332031になっている、怪しいことこの上ない
- 300件程度では学習ができないのか、教師データの作り方が間違っていたのか不明
- web上で調べたデータでは3,000件からの学習データを用意しているので、少なすぎなのかなぁと首をかしげていました
改善案2
- 投稿してみると、関連記事に「scikit-learnとgensimでニュース記事を分類する」があったので読んでみた
- その結果、名詞に絞った方がよさそうなことが分かった
- また、300では少なすぎるならば、分類をSocietyとEconomyに絞って、それぞれ1561件にしてみることにした
- 上と同じようにcategorized_file_list.txtを操作して件数を調整
grep Society categorizd_file_list3.txt | wc
1561 1561 87969
grep Economy categorizd_file_list3.txt | wc
1561 1561 87867
grep Politics categorizd_file_list3.txt | wc
0 0 0
- トークンを名詞だけにするようにスクリプトを改変
- 具体的にはmake_training_data.pyのdef get_token(content):内の処理
make_training_data.py
def get_token(content):
tokens = []
tagger = MeCab.Tagger('')
tagger.parse('')
node = tagger.parseToNode(content)
while node:
if node.feature.split(',')[0] == '名詞':
tokens.append(node.surface)
node = node.next
return tokens
- これでモデルを再作成してまとめて分類してみた
- 「しいて言えば、SocietyとEconomyのどちらか」の分類が出来るはず
python make_training_data.py categorized_file_list3.txt dictiory3 > training_data3.txt
python make_model.py training_data3.txt model3
python fasttext_test.py model3.bin dictiory3 all_file_list.txt > result3.txt
- 結果ファイルを見ると、マシになっていた
- 一ジャンルに1000文書以上は必要のようだ
result3.txt
/home/hoge/text/dokujo-tsushin/dokujo-tsushin-5619249.txt ['Economy:0.53125', 'Society:0.466797']
:
/home/hoge/text/it-life-hack/it-life-hack-6306744.txt ['Society:0.5', 'Economy:0.498047']
:
/home/hoge/text/kaden-channel/kaden-channel-6249654.txt ['Economy:0.501953', 'Society:0.496094']
:
/home/hoge/text/kaden-channel/kaden-channel-6250765.txt ['Society:0.511719', 'Economy:0.486328']
- 中を少し見てみる
dokujo-tsushin-5619249.txt
6月9日「ロックの日」10周年記念に“MIWA ROCK!!”に新モード「HARD」が追加
MIWA ROCK!!
- 上記の記事のスコアは['Economy:0.53125', 'Society:0.466797']
- あぁ、このに分類には入らないものを強引に入れてるので理不尽感が漂う
it-life-hack-6306744.txt
毅然とした態度で臨んでいく!グリー田中社長が訴訟の判決にコメント
グリーは2012年2月23日、ディー・エヌ・エー及びORSOを被告とする著作権侵害差止等請求訴訟(以下「本訴訟」)を提起していたが、本日、東京地方裁判所より、ディー・エヌ・エーらに対して、同社への損害賠償として2億3,460万円の支払い及び「釣りゲータウン2」の配信行為等の差止を命じる判決が下されたことをあきらかにした。
- 上記の文書のスコアは['Society:0.5', 'Economy:0.498047']。まぁ社会情勢っぽいから、Society優勢は分かる
kaden-channel-6249654.txt
どうしたmixi! 減収減益で最終損益は61.6%減の4億7,400万円【ニュース】
人気SNS「mixi」が2012年3月期第3四半期の連結業績を発表した。これによると最終損益が前年同期比△61.6%の4億7,400万円となり、減収減益だった。「mixiゲーム」による課金売上は順調に拡大しているが、スマートフォン利用の拡大に伴うモバイル広告の出稿減少が原因だという。
はっきりと数字が出たことにより、ネット上では「もうダメなのか?」「衝撃!」などいう驚きのコメントが見られる。
- 上記の文書のスコアは['Economy:0.501953', 'Society:0.496094']。わずかな差だが、確かにEconomyっぽい内容に見える
- 以上から、「一分類1500文書程度の教師データがあると、最低限の分類が出来そう」と分かった
- 少なくとも常にどちらかに判定されたり、同じ値が出続けることは無くなった
おわりに
- 今回の試みは納得のいかない結果に終わった
- 得られた教訓は教師データ作成の難しさだった
- pythoの基本的なコーディングとfasttextの基本的な使い方が分かったので良しとする