読者です 読者をやめる 読者になる 読者になる

svmでサイコパスシステム作ってみたかったけど出来なかった話

これは結局うまく行かなかったもののただのメモ書きですのであしからず。

なんの参考にもならないよ!

でも、もし賢い方でしたら僕に教えてください!!

 

背景の背景

LibSVM - 音声メモ

↑これがわかりやすかったので、使ってみようかなって思ったのが始まりです。

 

背景

 

犯罪者のツイッターアカウントとか結構残ってますよね。

 

最近だとアイドルを刺しまくった事件とか、ちょっと前だと浦安での通り魔とかの人のツイッターアカウントが話題になっていたと思うのです。

そういう人のつぶやきって、頻出単語も全然違うけどちょっと似てるところを感じたのが作ろうと思ったきっかけです。

 

それらのつぶやきデータを使って機械学習とかしてこのアカウントのは危ない人かどうか判定をできるようにしてみたかったのです。

とりあえず、犯罪者のつぶやきに似ている人は危ない人ということです。

 

 

犯罪者のツイッター情報あつめ

 

vipper-trendy.net

 

pixls.jp

 調べたら出てくるものですね・・・

こういう風に、ネットで調べて出てきた人のツイッターのつぶやきのテキストを280メガバイト文を学習データに使いました。

 

  • 問題点

犯罪を犯した人のツイッターアカウントってすぐに凍結されちゃう。

 

アイドル刺した人も凍結されてます。さっさと保存しておけばよかった。

 

 

 

とりあえず、おこなったことですが、、、

 

 

3グラムに分けて素性を作る

自然言語処理だとNグラム使うのがポピュラーらしいのでとりあえず、文章を分かち書きして、3グラムずつにわけて素性にしました。

 

文を形態素で分けることを分かち書きといいまして、mecabさんで簡単に出来ます。

f:id:alakialaca:20170322155628p:plain

 

今から遊べる人ー

を3グラムに分けると

f:id:alakialaca:20170322160358p:plain

となります。

 

f:id:alakialaca:20170322181650j:plain

 

こういうことです!

 

同じ場所に同じ単語があれば、素性の値も同じにして、素性を作っていきました。

 

f:id:alakialaca:20170322184557p:plain

という文章があれば、素性は以下のようになります。

f:id:alakialaca:20170322184641p:plain

 

そうして、犯罪者の人から作った素性のラベルは+1一般人からの素性のラベルは-1としました。

ちなみに一般人は僕が見る限り、「今日はカラオケ行った!」とか、いつも今日もしょうもないことつぶやいているわ〜って思わせてくれる方たちのつぶやき、280メガバイトを入れました。

 

 ↓が中身です。

 f:id:alakialaca:20170320211811p:plain

 

 

素性を作ったプログラムです。

僕頭がスパゲッティなので、容量の悪い書き方していますが、

#!/usr/bin/python
# -*- encoding: utf-8 -*-
#3/2作成

import sys
import re
from nltk.stem.porter import PorterStemmer
import MeCab
import glob

phyco = open("/home/araki/デスクトップ/phyco/twitter/box/phyco_feature.txt","w")


tagger = MeCab.Tagger('-Owakati')#これで分かち書きができる
dic = {}
feature_line =
id=1

files = glob.glob('/home/araki/デスクトップ/phyco/twitter/plus/*.txt')  #table内のtxtファイルすべてを取得
for file in files:  #txtファイルの数で回す。
  fp1=open(file,'r')
  for line in fp1:
    line = re.sub(r"@[_0-9a-zA-Z]+","",line)#@xxxxxxを消す
    line = re.sub(r"http://[_0-9a-zA-Z./]+","",line)#urlを消す
    line = re.sub(r"<br />","\n",line)#<br />改行を消す
    line = re.sub(r" ","",line)#空白も消す。
    line_mecab=tagger.parse(line)#分かち書きを行う
    line_mecab_split = line_mecab.split(" ")
    line_len = len(line_mecab_split)
    for line_sp_seg in range(0,line_len-3):
      phyco.write("+1 ")
      feature_line =

      for sp_count in range(0,3):
        s = str(sp_count+1) +"&"+line_mecab_split[line_sp_seg+sp_count]#数字&言葉を入れていく 例 2&言葉
        if not s in dic:#辞書の中になかったら
          feature_line.append(str(id)+":1 ")
          dic[s] = id#辞書に数字をあてがう
          id += 1
        else:#辞書の中にあったら
          feature_line.append(str(dic[s])+":1 ")
      num_files = [(int(re.search("([0-9]+):", x).group(1)), x) for x in feature_line]#ソート
      num_files.sort(key=lambda x:x[0])
      feature_line = [x[1] for x in num_files]
      for k in range(0,len(feature_line)):
        phyco.write(feature_line[k])
      phyco.write("\n")
'''
files = glob.glob('/home/araki/デスクトップ/phyco/twitter/mainus/*.txt')  #table内のtxtファイルすべてを取得
for file in files:  #txtファイルの数で回す。
  fp1=open(file,'r')
  for line in fp1:
    line = re.sub(r"@[_0-9a-zA-Z]+","",line)#@xxxxxxを消す
    line = re.sub(r"http://[_0-9a-zA-Z./]+","",line)#urlを消す
    line = re.sub(r"<br />","\n",line)#<br />改行を消す
    line = re.sub(r" ","",line)#空白も消す。
    line_mecab=tagger.parse(line)#分かち書きを行う
    line_mecab_split = line_mecab.split(" ")
    line_len = len(line_mecab_split)
    for line_sp_seg in range(0,line_len-3):
      phyco.write("-1 ")
      feature_line = []
      for sp_count in range(0,3):
        s = str(sp_count+1) +"&"+line_mecab_split[line_sp_seg+sp_count]#数字&言葉を入れていく 例 2&言葉
        if not s in dic:#辞書の中になかったら
          feature_line.append(str(id)+":1 ")
          dic[s] = id#辞書に数字をあてがう
          id += 1
        else:#辞書の中にあったら
          feature_line.append(str(dic[s])+":1 ")
      num_files = [(int(re.search("([0-9]+):", x).group(1)), x) for x in feature_line]
      num_files.sort(key=lambda x:x[0])
      feature_line = [x[1] for x in num_files]
      for k in range(0,len(feature_line)):
        phyco.write(feature_line[k])
      phyco.write("\n")
'''

 

 

libsvmを使ってみようとおもったけど、わからなかった。

 

 

libsvmさんを使ってスケーリングして、学習と思ったのですが・・・

svm-scaleは通ったのに、svm-trainは出来ないかった・・・

よくわからない・・・

f:id:alakialaca:20170322185752p:plain

 

とりあえず、スケーリングなしで学習してみました。

f:id:alakialaca:20170322193035p:plain

そして、学習用データに対してsvm-predictを使ってみたら、

f:id:alakialaca:20170322193059p:plain

5文交差検定

f:id:alakialaca:20170322193111p:plain

54%ってほとんど使い物にならないのでは・・・ 

 

偉い方に聞いてみた

偉い方ととは学校の先生のことです。

犯罪者のツイートだからといって、いつでも危ないことをつぶやいているわけではない。

同じ言葉を一般人も犯罪者も言っているはず、それだとノイズが多いため予測はできなさそう。

tf-idfを使ってありきたりな言葉を外したりCNN(Convolutional Neural Network)を使ったりword2vecを使って単語の塊をベクトルにして見た方がいいのではと言われた。

あとは言語からセンチメントを測ったりして素性を増やしたり、

いっそ、このツイートは危ないことを行っているから☓、これは普通のことを行っているから◯みたいにして素性にしたほうがいいのではないかと言われたが、それではキーワードマッチングになってしまう。

あとは。根本的にデータ量が少ないとも言われましたね。

 

 

svm-predictがわからない。

とりあえず判別させてみたいなーとおもってsvm-predictを自分のアカウント情報を入れて試してみました。

 

y-uti.hatenablog.jp

先頭列に正解のラベルが付きますが、これは正解率の計算のために使われるだけで、もちろん分類の際には利用されません。

っと書かれていたため、とりあえず0のラベルを付けて行ってみたらAccuracyは0になるのは当たり前だとして、output.txtの中身が全部1になっていました。

犯罪者データの内の一人の素性を使ってみてもラベルが1なのでAccuracyは100ですがoutput.txtは全部1になっていました。

わからない・・・

f:id:alakialaca:20170322195946p:plain

 

 

確率推定もできない。

d.hatena.ne.jp

確率推定をしたらサイコパス度を図れるかと思ったので素性作るプログラムの+1を1に-1を0に変えて-b 1 のコマンドを試してみたのですが、、、

 

f:id:alakialaca:20170322202419p:plain

model does not support probablity estimatesと出てきた・・・

 

 

だめだ。

だれも俺を愛さない。

 

っとまでが今の現状です。