[機械学習] : Multi-Class Classifier of Bra Size used as the feature value with vital statics
Multi-Class Classifier of Bra Size
アダルトフィルタ実装に向けたA○女優リストの自動抽出 + α - Yuta.Kikuchiの日記
前回のA○女優リストの自動抽出の流れから今日は実験を行います。本来の目的だったアダルトフィルタ作成から話がどんどんズレて行きます。今日のお題はVital Staticsを特徴量としてBra SizeのMulti-Class問題を解きます。タイトルを英語にしたのはこの下らない実験をさも真面目な研究としてやったかのようにカモフラージュするためです。初めに断っておきますが今回の実験を振り返った結果、反省はしている、だが後悔もしている状態です。
Vital Statics - Wikipedia
一般的な話ですがVital StaticsからBra Sizeを導きだすのは難しいとされています。( BraSize = TopBust - UnderBust。UnderBust ≠ Waist ) 確かに個人のVital Staticsからは算出は難しいのかもしれませんが、集団データから傾向の推定はできるのでは無いかというのが今回の実験のテーマです。下のようにBraの項目が欠損している方もいるのでそこをMachine Learningの力で補完して行きます。Name:瑠川リナ Bust:81 Waist:57 Hip:83 Bra:D65 Name:☆LUNA☆ Bust:83 Waist:57 Hip:82 Bra:D-65 Name:RUMIKA Bust:82 Waist:60 Hip:85 Bra:C Name:麗花 Bust:88 Waist:58 Hip:87 Bra:E Name:Reo. Bust:92 Waist:60 Hip:87 Bra:G Name:麗奈 Bust:88 Waist:60 Hip:85 Bra:D Name:れのん Bust:85 Waist:56 Hip:82 Bra:E Name:若瀬千夏 Bust:87 Waist:53 Hip:80
LIBLINEAR -- A Library for Large Linear Classification
Vital StaticsのVectorDataを学習させるのでSVMを利用します。利用するツールはLIBLINEARにします。
Experimentation
Making DataSet
Data/ero.tsv at master · yutakikuchi/Data
まずは上のDataを基にLIBLINEARに入れるDataSetを作成します。下にDataSetを整形するPythonスクリプトを載せておきます。FeatureはBust×Waist、Bust×Waist×Hipの2種類用意します。LIBLINEARの入力Formatに合わせてBra SizeもInt型のVectorに変換してClassのLabel名とします。#!/usr/bin/env python # -*- coding: utf-8 -*- # AdultFilter # Bra Size Map bramap = { 'A':0, 'B':1, 'C':2, 'D':3, 'E':4, 'F':5, 'G':6, 'H':7, 'I':8, 'J':9, 'K':10, 'L':11, 'M':12, 'N':13, 'O':14, 'P':15, 'Q':16, 'R':17, 'S':18, 'T':19, 'U':20, 'V':21, 'W':22, 'X':23, 'Y':24, 'Z':25 } # key map keymap = { 'Bra':0, 'Bust':1, 'Waist':2, 'Hip':3 } # logic ef = open( 'ero.tsv', 'r' ) data = ef.read() ef.close() df2 = open( '2feature_data.txt', 'w' ) df3 = open( '3feature_data.txt', 'w' ) datalines = data.split( "\n" ); for line in datalines: try: nodes = line.split("\t") if len(nodes) < 5: continue list = [0]*4 for node in nodes: try: (key,value) = node.split(":") if key == 'Name': continue elif key == 'Bra': alpha = value[0].upper() if alpha.isalpha() == False: continue list[keymap[key]] = str( bramap[alpha] ) else: if value.isdigit() == False: continue list[keymap[key]] = str( keymap[key] ) + ':' + str( value ) except Exception,e: continue df3.write( ' '.join(list) + '\n' ) del list[3] df2.write( ' '.join(list) + '\n' ) except Exception,e: continue df2.close() df3.close()2 Feature Sample Data
$ head -n 10 2feature_data.txt 10 1:110 2:70 4 1:85 2:58 8 1:96 2:61 5 1:85 2:60 4 1:80 2:60 5 1:87 2:60 5 1:88 2:60 4 1:80 2:59 7 1:90 2:59 4 1:84 2:603 Feature Sample Data
$ head -n 10 3feature_data.txt 10 1:110 2:70 3:90 4 1:85 2:58 3:88 8 1:96 2:61 3:87 5 1:85 2:60 3:85 4 1:80 2:60 3:84 5 1:87 2:60 3:84 5 1:88 2:60 3:87 4 1:80 2:59 3:85 7 1:90 2:59 3:86 4 1:84 2:60 3:88
ちなみにDataSetの分布をGraph化すると次のようになります。全く関係ありませんが、心が辛い時はこの分布を見ると少しばかり勇気をもらえるかもしれません。当然この標本Dataはエリート集団属性になりますので、世間一般の分布と勘違いされないようご注意ください。分布抽出のコマンドも下のようになります。
$ cut -f 1 -d " " 3feature_data.txt | sort | uniq -c | sort -k 1 -n -r | awk '{print $2 " " $1}' 4 539 3 475 5 440 6 260 7 240 2 137 8 83 9 47 10 26 1 14 11 12 12 3 17 2 16 2 13 2 15 1 14 15-Fold Cross Validation
線形予測の機械学習ツールliblinearで効果最大化のための最適な定数Cを探る - Yuta.Kikuchiの日記
上で作成したDataSetを基に5-Fold Cross Validationを行います。LIBLINEARの設定や使い方は上の記事を参考にしてください。
実行した結果ですがBust×Waistで31.6112%、Bust×Waist×Hipで32.6182%となりました。Hipというあまり関係なさそうな説明変数もちょっぴり精度向上に貢献していました。結果としてMulti-Classを解く問題としては中々の精度なのではないでしょうか。
Feature Accuracy Bust×Waist 31.6112% Bust×Waist×Hip 32.6182% $ train -v 5 -s 2 2feature_data.txt Cross Validation Accuracy = 31.6112% $ train -v 5 -s 2 3feature_data.txt Cross Validation Accuracy = 32.6182%Prediction
目的であったData補完の話を進めます。欠損していたBra Sizeを推定で埋めて行きます。5-Fold Cross Validationを行ったデータをTraining DataSet、Vital StaticsはあるけどBra Sizeが無いものをPrediction DataSetとします。Prediction DataSetは以下のPythonコードとLinuxコマンドで生成します。円GraphはClass毎の割合比較、棒Graphは青がOriginDataの人数/橙がPredictionによって推定された人数を追加した合計人数になります。割合を見てみるとC〜Fの持ち主が全体の75%という結論になりますね。
#!/usr/bin/env python # -*- coding: utf-8 -*- # AdultFilter # key map keymap = { 'Name':0, 'Bust':1, 'Waist':2, 'Hip':3 } # logic ef = open( 'ero.tsv', 'r' ) data = ef.read() ef.close() dp = open( 'prediction_data.txt', 'w' ) datalines = data.split( "\n" ); for line in datalines: try: nodes = line.split("\t") if len(nodes) != 4: continue list = [0]*4 for node in nodes: try: (key,value) = node.split(":") if key != 'Name' and value.isdigit() == False: continue list[keymap[key]] = str( keymap[key] ) + ':' + str( value ) except Exception,e: continue print list dp.write( ' '.join(list) + '\n' ) except Exception,e: continue dp.close()$ cut -f 5 ero_prediction.tsv | sed "s/Bra://g" | sort | uniq -c | awk '{print $2 " " $1}' C 325 D 241 E 23 G 21
補完したデータは以下のように抽出されました。前回と同様にGithubに上げておきます。
Data/ero_prediction.tsv at master · yutakikuchi/Data$ head -n 10 ero_prediction.tsv Name:愛内希 Bust:80 Waist:57 Hip:83 Bra:C Name:愛内萌 Bust:86 Waist:56 Hip:82 Bra:E Name:相川とも子 Bust:83 Waist:56 Hip:83 Bra:D Name:愛川ひな Bust:83 Waist:57 Hip:85 Bra:C Name:藍川めぐみ Bust:95 Waist:60 Hip:88 Bra:G Name:あいかわ優衣 Bust:86 Waist:60 Hip:87 Bra:C Name:逢坂あきら Bust:86 Waist:59 Hip:88 Bra:C Name:愛咲めぐ Bust:86 Waist:60 Hip:84 Bra:D Name:愛咲ゆかり Bust:92 Waist:59 Hip:88 Bra:E Name:愛沢美理 Bust:80 Waist:59 Hip:84 Bra:C
Conclusion
今回の実験で以下のような結果を得る事ができました。
- FeatureにはBust×WaistよりもBust×Waist×Hipを使う方が精度が少しだけ上がる。
- 5-Fold Cross Validationの結果でFeatureをBust×Waist×Hipとした場合、精度は32%だった。
- 推定値を合わせた結果でもC〜Fの持ち主が全体の75%という驚異的な数値。
優秀なデータサイエンティストの方へ
この研究に興味を持たれた方は是非引き継いで、話を面白い方向性に膨らませて欲しいです。僕はこれ以上やりません笑