The night, and the dream, were long...
はじめに
この記事はklis Advent Calendar 2017の21日目の記事です.
昨日はktmnさん(@piyopiyo_tititi)の生活にアザラシを取り入れてから気が楽になった話 - 日記という記事でした. あざらし可愛いですね. 短気なので生活にあざらしを取り入れていきたいと思います.
さて,この記事の題目となっている"The night, and the dream, were long..."というセリフをご存知でしょうか.
"The night, and the dream, were long..."は,"Bloodborne"のラスボスの一人であるゲールマンのセリフです.
私(@lapis_zero09)は現在klis14の学生で卒業を間近に控えておりますが,大学生活は長いようで短く,夢のように過ぎ去っていきました. まだ残ったモラトリアムも有意義に過ごしたいです.
Bloodborneについて
さて,くさいセリフは置いておいてBloodborneは,FromSoftwareより出ているゲームです.
FromSoftwareは,Bloodborneの他に"DarkSouls"や"ARMORED CORE"などのソフトを出していることで知られています.
Bloodborneは,DarkSouls,及び,Demon's Soulsと並んでソウルシリーズと呼ばれ,その雰囲気やスタイリッシュさから壮絶な人気を博しています*1*2.
また,Bloodborneは,"死にゲー"と呼ばれるほど難しく,かっこよさに惹かれ,始めたはいいものの途中で攻略を諦める人が後を絶ちません*3. しかし,その難しさを諸共せず,あるいは難しさに惚れ込み,四六時中このゲームのことを考えたり,プレイしたりする人間もおり,そのような人は地底人と呼ばれています*4.
このBloodborneは,その他のFromSoftwareの作品と同様,ほとんどと言って良いほどゲームの世界観を伝えるNPCの台詞やムービーが無く,解釈の一切をユーザに委ねています. このことから,フロム脳を患うユーザが後を絶ちません. フロム脳とは,ゲームの設定を必要以上に考察してしまう精神病の一種で,重度の場合,現実世界の事象についても考察し始めます*5. フロム脳罹患者によるBloodborneに関する考察や2次創作は後を絶ちません.
フロム脳の発症者の中には高い技術力や文才を持った者もおり、こういった人々の解釈・考察・動画は作品の世界を更に広げていく可能性を持っているため、フロム脳をただの妄想癖と言って悪く決めつけきれないところがある。
出展:フロム脳とは (フロムノウとは) [単語記事] - ニコニコ大百科
前置きが長くなりましたが,この記事は何らかの形でBloodborneの二次創作を作成し,Bloodborneをより多くの人に知ってもらうと共に,Bloodborneを盛り上げ,フロム脳患者を増やし,あわよくばBloodborne2の発売を願うものです.
二次創作
そもそも私が,Bloodborneにハマったのは中の良い二人の悪いオタクが主な原因です. ある日,いつものようにたまり場にいる時,二人の悪いオタクが「お前もやってみろ」と私にPS4のコントローラを渡し,気づけば,無意識にBloodborneのことを考え,作業中にBloodborne考察動画を流し,また,大学から家までの道のりにある木の位置や階段の段数を考察するフロム脳の自分がいました.
そして,Bloodborneにハマった要因の一つに,"original soundtrack(以下,OST)の良さ"があります.楽団と聖歌隊によるコーラスによって重厚な曲は作業用のBGMに向いており,この記事の執筆時にも流しているほどです.
Amazon Musicにあるので是非聞いてみてください.
一方で,人間,同じ曲ばかり聴いていると飽きが生じてしまうもので,Bloodborneそのもののプレイにも支障を来すことになり兼ねません. OSTに含まれる曲数は限られ,ゲームの続編が出ない限りサウンドトラックが増えないことは想像に難くないでしょう.
なので,この記事では似たような曲を作ることを二次創作とします.
しかし,私はピアノやギターは弾いたりするものの作曲に関しての知識は毛頭ありません.
そこでその辺の機械学習ラボに属している私らしく機械学習によって作曲することを考えます.
作曲
まず,私が所持している音楽データは全てステレオmp3形式なので,音楽を学習・生成するニューラルネットワークを設計するために,ニューラルネットが理解できる形式に変換する必要があります.
皆さんご存知の通り,音波は連続的な信号であり,無限のデータ点に分割することが可能です. サンプリングでは,サンプリング周波数で決まる一定の時間間隔で信号の値を保存します. したがって,サンプリングによって無理やり有限のデータで連続信号を表すことを考えます. サンプリング周波数は44100Hzに設定しました. 一般的に,人間の耳は,20000Hzまでの周波数を聞き取ることができると言われています. したがって,20000Hzを超える周波数が存在しても,違いはないと想定します. また,Nyquist–ShannonのSampling Theorem*6によると,サンプリング周波数は20000Hzのほぼ2倍にする必要があります. したがって,44100Hzは理論的に学習可能なサンプリング周波数とみなすことができます.
次にステレオmp3をモノラルmp3に変換することで,音楽を空間性を持たないものに変換します. モノラルであるということは,例えばイヤホンで音楽を聞いた時,左右の耳から聞こえる音が同じであることを示しています. 簡単に言えば,モノラルサウンドは,ステレオサウンドを表現するために必要なマトリックスのサイズの半分で表現することができます. これにより,ニューラルネットワークを訓練するのにかかる時間だけでなく,必要なメモリも削減することができます.
しかし,モノラルに変換したと言えど,mp3は,圧縮形式であるというのには変わりなく,まだニューラルネットで学習するのに優れた形式ではありません. そこで,モノラルmp3をWAV形式に変換します. WAV形式は,FLAC以外に最も簡単に利用できる非圧縮オーディオであり,pythonライブラリであるscipyによって簡単に扱うことができます. これで,時間領域で圧縮されていないサンプリングされたオーディオ形式が得られました.
さらに,WAVファイルをニューラルネットが理解できるものに変換します. ニューラルネットに時間信号の異なる周波数をよりよく理解させるために,離散フーリエ変換(以下FFT)を使用して,時系列の複雑なデータを対応する周波数領域に変換しました. これで前処理の終わりではなく,FFTの出力は複素数の配列であり,ニューラルネットワークの入力にするために実数部と虚数部に分割する必要があります. また,時間が一致しないものはゼロパディングを行いました.
これにより,元のステレオmp3データは3次元のテンソルとして構造化することができました. この3次元マトリックスをニューラルネットに与えることで音楽を生成します. これで前処理のタスクは終了しました.
次に発生する問題はニューラルネットのアーキテクチャーをどう設計するかです. リカレントニューラルネットワーク(以下,RNN)は音声のような時系列データを扱うのに最適なニューラルネットワークです. シーケンスのすべての要素(このケースではテンソル)に対して,事前定義された操作を繰り返し実行するため,リカレントと呼ばれます. 重要な点は,次の一連の操作でも,前の計算の結果が考慮されることです. したがってRNNには情報を記憶できるmemoryがあることがわかります. 音楽データに対して考えると,ネットワークに一連の音符を与え,それはシーケンス全体を通って次の音符を予測します. しかしノーマルのRNNには,長い間情報を保持することができないという欠点があります. そこで,Long Short Term Memory(以下,LSTM)が提案されています. LSTMでは,セルと呼ばれる別のベクトルが情報を記憶するために用いられています. LSTMの大きな利点の1つは,学習する必要のあるパラメータの数が従来のネットワークに比べて少ないことです. 情報の転送・更新,出力の生成のための重みとして機能する基本的に3つの行列があります. 3つの行列は、シーケンスの各要素に対して操作を実行するために繰り返し使用されます RNNやLSTMに関するより詳細な情報はDeep Learning Book*7などを参照してください.
今回は,自前のGPUを使用したため計算的リソースは非常に限られており,浅いネットワークを構築しましたが,訓練には数日を要しました. モデルの生成と学習にはkerasを使用しました.
以下が生成した音楽例になります.
最初の方は良さげですね.
もっと潤沢なリソースで複雑なネットワークを扱うことでより皆さんの感性に合う音楽が作れるかもしれません.
最後に
明日は卒論の提出日ですが,最後まで気は抜けないのでそろそろ寝ることにします.
明日のklis Advent Calendar 2017はまっつんさん(@crc9dijo)の担当ですが,卒論の話が聞けるかもしれません.
おやすみなさい.
商品を買ってFromSoftwareを応援しよう!!
Bloodborne The Old Hunters Edition 通常版 [PlayStation4]
- 出版社/メーカー: ソニー・コンピュータエンタテインメント
- メディア: Video Game
- この商品を含むブログを見る
- 出版社/メーカー: ソニー・インタラクティブエンタテインメント
- 発売日: 2015/03/26
- メディア: Video Game
- この商品を含むブログ (4件) を見る
DARK SOULS III THE FIRE FADES EDITION - PS4
- 出版社/メーカー: フロム・ソフトウェア
- 発売日: 2017/04/20
- メディア: Video Game
- この商品を含むブログを見る
DARK SOULS III 特典無し [PlayStation4] - PS4
- 出版社/メーカー: フロム・ソフトウェア
- 発売日: 2016/03/24
- メディア: Video Game
- この商品を含むブログ (3件) を見る
ARMORED CORE VERDICT DAY(アーマード・コア ヴァーディクトデイ)(通常版) - PS3
- 出版社/メーカー: フロム・ソフトウェア
- 発売日: 2013/09/26
- メディア: Video Game
- この商品を含むブログ (12件) を見る
Mangakiチャレンジ
日記です.
Mangakiチャレンジに参加した.
マンガ・アニメを推薦するタスク
このコンペティションでは、アニメ・マンガに対するユーザの評価の予測に取り組んでもらいます。データセットとして、実際のユーザによる評価結果が提供されます。
0828に一発目を投げて,1位だったのでほったらかして結局4位だった.
暫定一位きたー pic.twitter.com/vMzjJgBR8j
— しんさく (@lapis_zero09) 2017年8月27日
予測タスクが簡単すぎた(?)のかどのモデルでもパフォーマンスが頭打ちの感
最終的にベースモデルにはSVMを使った.
評価値は,評価行列を作って,"ユーザ"と"アイテム"それぞれでクラスタリング(k-means).
クラスタ数は,施行により設定.
ユーザもアイテムも何千のオーダーだったけど,クラスタ数は一桁が一番良かった.
追加データも出たらしいけど見てない.
2位だった先輩の解法:http://nzw0301.github.io/2017/10/mangaki
このくらいのコンペなら隙間時間にできて良い.
意味表現学習まわり
CBOW, SG, GloVeについて
連続単語袋詰めモデル(continuous bag-of-words model,CBOW) と 連続スキップグラムモデル(continuous skip-gram model,SG) は Mikolovらによって提案された単語の分散的意味表現手法.
これらのモデルを公開しているツール→word2vec
CBOW
与えられた文脈の中で出現している文脈語を使って,ある対象語が出現しているかどうかを予測可能な意味表現を学習.
対象語 意味を表現したい単語 文脈語 ある単語の周辺に現れる単語
文について,
形態素は,[私,は,ご飯,と,味噌汁,を,食べた]
対象語を「ご飯」とすると,それ以外の語が文脈語として用い,「ご飯」の出現を予測.
CBOWモデルでは,文章中に[私,は,と,味噌汁,を,食べた]という文脈語が出現していた時に, その文章中に「ご飯」という単語が出現するかどうか予測できるように, それぞれの単語の意味表現ベクトルを更新することが目的.
1つの単語につき,次元のベクトル
番目の単語が対象語の場合,その単語の対象語ベクトルを使用.
番目の単語が文脈語の場合,その単語の文脈語ベクトルを使用.
対象語が文脈中のi番目の単語して出現している場合, を中心とする個の単語からなる文脈 を使って予測する問題を考える.
この文脈中に出現する文脈語についての文脈ベクトルを とすると対象語の出現確率は, と表すことができる.
→ を大きくするとより広い範囲で単語の共起が考慮可能.関係が低い離れた単語同士の共起も考慮されてしまう
→ はCBOWのハイパーパラメータ.Mikolovらはとして5単語からなる文脈窓を用いて学習
問題:長い連続する単語列の出現は大きなコーパスについても少ない→その出現確率を推定することは難しい
CBOWにおける解決策:文脈語の出現順序を無視,下式で与えられる文脈語ベクトルの平均ベクトルを,対象語の文脈を代表するベクトルとして用いる.
\begin{align} \hat{\boldsymbol{x}} = \frac{1}{2k}(\boldsymbol{z}_{i-k} + \cdots + \boldsymbol{z}_{i-1} + \boldsymbol{z}_{i+1} + \cdots + \boldsymbol{z}_{i+k}) \end{align}
とを用いて,対象語の出現確率をソフトマックス関数で以下のように計算
\begin{align} p(\boldsymbol{x}_i|\boldsymbol{z}_{i-k}, \cdots, \boldsymbol{z}_{i-1}, \boldsymbol{z}_{i+1}, \cdots, \boldsymbol{z}_{i+k}) = \frac{\exp(\hat{\boldsymbol{x}}^{\mathrm{T}} \boldsymbol{x})}{\sum_{x' \in \boldsymbol{\nu}}\exp(\hat{\boldsymbol{x}}^{\mathrm{T}} \boldsymbol{x'})} \end{align}
はコーパス中の全単語からなる語彙集合,は中の単語を表す
xが文章中に出現する可能性が高いほど右辺・分子の内積の値が大きくする
1つの単語について2つのベクトルが付与される(文脈語ベクトルと対象語ベクトル)→単語の共起をベクトルの内積で表現しているから
1つじゃダメなの?→1つの場合,の中にもが現れることになり,を小さくすることになる.
→ の長さ(l2ノルム)を小さくすることになる
→ のl2ノルムを変えてもソフトマックス関数はスケール不変
→ をそのl2ノルムで割って正規化しても の値は変わらない
→異なる2つのベクトルを使うことでこの問題を解決
tips:単語の共起頻度を離散的な数ではなく,連続な値(ベクトルの内積)でモデル化しているので「continuous」
上記では出現順序を無視し,文脈語の平均を使って文脈を表現したが,出現順序を保つベクトルを作成することも可能
→文脈語のベクトルを連結する
SG
対象語を使って,文脈に出現している文脈語を予測する
対象語の「ご飯」を持ちいて,他の単語([私,は,と,味噌汁,を,食べた])の出現を予測
対象語が番目の単語として出現している文脈で他の単語を同時に予測する場合の確率を下式で計算.
\begin{align} p(z_{i-k}, \cdots, z_{i-1}, z_{i+1}, \cdots, z{i+k}|x) = p(z_{i-k}|x)\cdots p(z_{i-1}|x)p(z_{i+1}|x)\cdots p(z_{i+k}|x) \end{align}
※対象語が与えられているとき,文脈語が全て独立
独立性の仮定により,
\begin{align} p(z|x) = \frac{\exp(\boldsymbol{x}^{\mathrm{T}} \boldsymbol{z})}{\sum_{z' \in \boldsymbol{\nu} (x)}\exp(\boldsymbol{x}^{\mathrm{T}} \boldsymbol{z'})} \end{align}
(→「わかりやすいパターン認識」など参照のこと)
は対象語xが出現している文脈中での文脈語の集合.ある特定の文脈でと共起する文脈語の集合ではなく,コーパス全体におけるが出現する全ての文脈に関しての文脈語の集合
CBOWと同様文脈として,対象語を中心とする個の単語からなる文脈窓を選ぶことも可能
→ を固定せずに,それぞれのの出現においてとしてある区間内のランダム値を取るなど,文脈窓の幅を動的に決めることも可能
個の単語それぞれについて,次元の対象語ベクトルを学習
それぞれの単語について何らかの文脈で共起する文脈語がなので,その単語全てについて次元の文脈語ベクトルを学習
CBOWはSGに比べ,文脈語の独立性を近似していないため,より正確
1対1の共起をモデル化しているSGに比べ,CBOWは1対複数の文脈語をモデル化しているので,複数の文脈語からなる単語列がコーパス中に十分な回数現れなければならない
→CBOWはより大きなコーパスが必要
CBOWとSGのモデル最適化
SGのモデルについて,
\begin{align} p(z|x) = \frac{\exp(\boldsymbol{x}^{\mathrm{T}} \boldsymbol{z})}{\sum_{z' \in \boldsymbol{\nu} (x)}\exp(\boldsymbol{x}^{\mathrm{T}} \boldsymbol{z'})} \end{align}
またはについて凸関数ではない→局所解が存在
のある要素に注目するととの内積はその要素に対して線形な関数となる
かのどちらかを固定した場合,片方の関数について上式は凸関数となる→双線形関数,交互最適化可能
さらに,上式はを含むので対数をとることで対数双線形関数
かを固定すると片方の変数に関してソフトマックス関数→多クラスロジスティック回帰としてみなせる
負例サンプリング
SGのモデルについて,単語の分散的意味表現を学習するために, ある単語と共起する単語(正例)だけでなく, 共起しない単語(負例)に関する情報も必要
→共起しない単語集合は膨大.その中から学習のために「良い負例」を選択しなければいけない
→この負例手法のことを負例サンプリング(Negative Sampling)
SGのNegative Sampling
ある単語xの分散的意味表現を求める問題を考える
正例として扱える文脈語の集合をとし,負例の集合をとする
それぞれの定義より,
この時,SGモデルで定義される共起の予測確率に従い, 対数尤度を最大化するの対象語ベクトルは下式で与えられる
\begin{align} \hat{\boldsymbol{x}} = argmax_{x} (\sum_{z \in \boldsymbol{D}_{pos}} \log(p(t=1|\boldsymbol{x} ,\boldsymbol{z})p_{pos}(z|x)) + \sum_{z \in \boldsymbol{D}_{neg}} \log(p(t=-1|\boldsymbol{x} ,\boldsymbol{z})p_{neg}(z|x))) \end{align}
右辺第1項は対象語と共起する文脈語に関する対数尤度を表す. その項のは正例であることを示す.
はの正例集合での出現確率を表しており, 正例集合はコーパス中に出現している単語集合なので, となる
右辺第2項について,負例はランダムにサンプリングしているためサンプリング手法に依存する.
本来なら負例は正例を除いたからサンプリングすべきだが, に比べ,は極めて小さいため 近似的にをからサンプリングしている
→どの対象語についても同一分布が使える利点
サンプリング手法は?
→SGではコーパス中で高出現確率である単語が単語の意味表現学習の負例として選ばれるように,単語のユニグラム分布に基づいて負例集合を選択
負例がのペアで決まるのなら,ユニグラム分布ではなく,との同時分布からサンプリングすべきでは?
→2単語の同時共起確率に比べ,1単語の出現確率がゼロになりにくいという利点.
→膨大なコーパスから共起を計算するには大きな共起表を作らなければならず,空間計算量という点で好ましくない
単語の出現はZipfの法則に従うのではロングテールの分布となる.
→を3/4乗した値に比例する分布をサンプリング分布として用いている.
→出現確率が小さい文脈語zも比較的高頻度でサンプリングされるようになる
以上より,
はロジスティックシグモイド関数
第2項の負例に関するサンプリング分布はに無関係. よって,第2項を期待値の形で書き表すことが可能
1つの正例に対して,個の負例を用いる.
負例はランダムに選択している擬似負例のため正例数に比べ,負例数を大きくしなければならない.
実用的には.
word2vecに実装されているCBOWとSGでは, 非同期パラメータ更新による並列処理を行うことで学習時間の短縮
→複数のスレッドを用いて,同一学習モデルを更新していく.
→同じ学習モデルを更新すると互いに更新する値を打ち消しあう可能性,必ずしも正しく学習が行えるわけではない
より正確にするには
→オンライン学習の並列化でよく用いられるように反復的パラメータ混合方
→スレッドごとに独立にモデルを持たせて,独立的に学習させたモデルを足し合わせる
学習の正確さ トレードオフ 大量のデータから短時間で学習
階層型ソフトマックスによる近似計算
大規模なコーパスについて,多数の対象語と文脈語に関してベクトルを計算しなければならず, 高速に計算できることが望まれる.
\begin{align} p(z|x) = \frac{\exp(\boldsymbol{x}^{\mathrm{T}} \boldsymbol{z})}{\sum_{z' \in \boldsymbol{\nu} (x)}\exp(\boldsymbol{x}^{\mathrm{T}} \boldsymbol{z'})} \end{align}
右辺分母は全文脈語彙集合にわたって規格化しなければならず,この計算に時間がかかる
解決策
→単語の階層構造を事前に事前に用意し,それに従って規格化を行う→階層型ソフトマックス
→単語の出現を考慮する代わりに,その単語を含むグループを考慮できるので, 式中の和の計算を行う際に,考慮すべき語彙集合を小さくできる
ある単語xがある1つのグループにのみ含まれるようにグループ分けされていれば, 全単語集合ではなく,このグループ内でのみの確率を規格化しておけば良い
言語モデル構築の際に,単語そのものの出現頻度の代わりに,単語グループの出現頻度を使うことで出現頻度が少ない単語の出現確率を求める手法から発想を得ている
単語の階層構造をどのようにして作るか
階層的クラスタリングとWordNetを使って大規模なコーパスから単語の分散的意味表現を学習する際の問題点
階層的クラスタリングの場合
単語と単語間の類似度とグループとグループ間の類似度を計算しなければならないため,計算時間がかかる
どのような類似度尺度を使うべきかが明確ではない
- 階層的クラスタリングによって作られる階層構造が,類似度尺度によって変わる
WordNetの場合
- WordNetに登録されていない単語をどのように分類するか
word2vecではハフマン木を使うことで単語の階層構造を構築
→単語の出現頻度を計算し,出現頻度の高い順にソート
→階層的クラスタリングよりも計算量の点で有利
→コーパス中の全ての単語がハフマン木のノードで表されているので未知語の問題が起きない
単語の階層構造を用いて,どのようにして確率を計算するか
ハフマン木上で単語zに対する頂点を見つけ,根からその頂点への経路Path(z)を求める
各ノードではもしくはという2つの枝があるため,の予測確率をロジスティック関数を使って,次のように近似できる
は根から単語に対する葉への経路上のノードを表し,lは各ノードでの枝の値を表し, このlに対応する確率変数が
ハフマン木は単語の出現頻度だけを使って構築されているので, 単語の意味的関係を反映しているとは言えないが元の式を近似するには十分な階層構造である.
大域ベクトル予測モデル
CBOWとSGはコーパスを一文単位で処理し,単語毎の2つのベクトルを更新している
→単語の共起を予測する際に,一文に含まれている情報しか使うことができない
→分散的意味表現ベクトルを学習する際に一文中の共起共起情報ではなく, 分布的意味表現のように,コーパス全体における2つの単語共起情報を使う手法
→大域ベクトル予測モデル(global vector prediction,GloVe)
分布的意味表現のように,コーパス全体における対象語と文脈語のコーパス全体における共起頻度を計算し, 共起行列を作成
の各行が対象語・各列が文脈語に対応しているとする
→ 番目の対象語と番目の文脈語が共起する確率回数をの番目の要素
次の目的関数を最小化する対象語ベクトルと文脈語ベクトルを学習
\begin{align} J = \sum_{i,j=1}^{|\boldsymbol{\nu}|}f(X_{ij})(\boldsymbol{x}_i^{\mathrm{T}}\boldsymbol{z}_j + b_i + b_j - \log(X_{ij}))^2 \end{align}
とはスカラーのバイアス項
→対象語ベクトルと文脈語ベクトルの内積を用いて,この共起頻度の対数を予測
関数は次の3つの性質を満たす関数
のときが有限の値を持つ.
- 共起頻度が0であるペアに関してもが無限大に発散してしまうのを防ぐ
は単調増加関数.
低共起頻度のペアを過剰評価するのを防ぐ
はある閾値以上の共起頻度に関しては比較的小さな値を持つ
- 不要語など高頻出する単語との共起を過剰評価するのを防ぐ
GloVeはに下式を採用
$$ f(t) = \begin{array}{} (t/t_{max})^\alpha & (t < t_{max}) \\ 1 & (otherwise) \end{array} $$
はあるいはのどちらか一方を固定させた場合, 片方に対して線形であり,双線形関数.
→交互最適化手法
- GloVe → 目的関数が二乗誤差
- CBOW SG → 交差エントロピー誤差
GloVeがCBOW SGと大きく異なる点→負例を必要としない
→負例サンプリングを行うための様々な仮定や近似が不要になる
個の単語の共起情報を保存するためには個の変数(自分自身の共起は計算しないので)が必要となる
→空間情報量としてはのオーダーの変数が必要
→共起行列をどのように計算するかがGloVeを用いて学習するための重要な前処理タスク
→実際どうするか
- 分散処理
- コーパス全体における各単語の出現頻度を求め,頻度が小さいものは共起行列に含まないようにする.
- 出現頻度の低いもの→スペルミスの可能性
- 出現頻度が低いと共起の可能性も低い→信頼できる統計情報が得られない可能性
- 共起行列を構築するために最低2回コーパスを処理しなければならない
→CBOWとSGは一文単位で学習できるのでオンライン学習が可能
意味表現の評価
分散的意味表現において,ベクトルの各次元がどのような意味に対応しているか分かっていない
→学習された意味表現を別のタスクに応用し, その応用先タスクにおける精度がどれくらい出るかで正確さを評価
→間接的評価方法
→評価対象を直接評価→直接的評価方法
間接的評価方法
→CBOWやSGでは分散的意味表現を学習するのにある文脈において2つの単語が共起するかを予測している
→共起が正確に予測できているかで評価可能
単語の意味表現の正確さを評価するために用いられるタスク
- 2つの単語間の意味類似性を予測するタスク
- 2つの単語ペア間の関係類似性を予測するタスク
意味的類似性予測タスク
単語同士の意味がどれくらい似ているか (意味的類似性(semantic similarity))を求めることができれば, 意味が近い単語同士に高い類似性スコアが計算できるかどうかで 意味表現そのものの正確さを間接的に評価可能
意味的類似性は類義性(synonymy),関連性(relatedness)よりも広義な概念
例:「暑い」と「寒い」という対義語について 温度という属性は共通しているので意味的類似性が高い単語ペア
使ってみる
上記のCBOW,SG,GloVeに加え,分布的意味表現を日本語記事に対して適用してみる.
コードはここ(https://github.com/lapis-zero09/compare_word_embedding)に
全記事に対して,preprocess.pyで形態素解析を行い,gensimで処理可能な形にする.
解析器にはMeCabを用いて,辞書はipadic-nelogd
glove_pythonの導入に戸惑ったMacユーザは以下のREADMEを参照すると良いかも
https://github.com/lapis-zero09/compare_word_embedding
全ての形態素の原型を取り出し,一記事を一行にまとめる.
それぞれの学習は,
$ python w2v.py $ python glove_train.py $ python ppmi.py $ python svd.py
それぞれイテレーション10,windowサイズ10,次元指定できるものは100次元で学習させた結果が以下
いずれもiphoneの類語を予測
CBOW_with_hs [('iphone4', 0.515411376953125), ('webブラウザ', 0.4230906665325165), ('ios6', 0.4147755801677704), ('ipad', 0.4116036593914032), ('ipad2', 0.38188278675079346), ('アップル', 0.37905681133270264), ('iphone4s', 0.367786169052124), ('ソフトバンクbb', 0.36410054564476013), ('タンブラー', 0.36315712332725525), ('大丈夫', 0.35265758633613586)] CBOW_with_ns15 [('iphone4', 0.6266778707504272), ('ipad', 0.6240962743759155), ('touch', 0.6063281297683716), ('ipod', 0.5750889778137207), ('ios', 0.5344790816307068), ('4s', 0.5055159330368042), ('アップル', 0.49820417165756226), ('ipad2', 0.4975413680076599), ('防水ケース', 0.4778713583946228), ('kobo', 0.47309401631355286)] CBOW_with_hs_ns15 [('iphone4', 0.5731303691864014), ('iphone4s', 0.4358748197555542), ('ios', 0.42091381549835205), ('ipad2', 0.41879040002822876), ('アップル', 0.41285741329193115), ('防水ケース', 0.3713395595550537), ('ios6', 0.3705442547798157), ('ソフトバンクbb', 0.3699251115322113), ('ホカホンhd', 0.3648505210876465), ('コネクター', 0.36398276686668396)] SG_with_hs [('4s', 0.7601545453071594), ('ipod', 0.7516292333602905), ('ipad', 0.7158170938491821), ('touch', 0.7114615440368652), ('ios', 0.6660245656967163), ('第4世代', 0.6656962037086487), ('3gs', 0.6580607891082764), ('iphone4', 0.6171021461486816), ('配布', 0.5599908828735352), ('互換', 0.551994264125824)] SG_with_ns15 [('ipad', 0.7440428733825684), ('4s', 0.741912305355072), ('ipod', 0.7315280437469482), ('3gs', 0.7070977091789246), ('touch', 0.672669529914856), ('ios', 0.6507753729820251), ('iphone4', 0.6480903625488281), ('第4世代', 0.6351419687271118), ('for', 0.6325072050094604), ('フリーペーパー', 0.5929508209228516)] SG_with_hs_ns15 [('ipod', 0.7355147004127502), ('4s', 0.7283318042755127), ('ipad', 0.7088928818702698), ('touch', 0.6909142732620239), ('3gs', 0.6866996884346008), ('ios', 0.6676512956619263), ('iphone4', 0.6078430414199829), ('フリーペーパー', 0.6007919907569885), ('配布', 0.6005358695983887), ('第4世代', 0.6001726388931274)] glove [('ipad', 1.7425963151785258), ('アプリ', 1.4982636197187946), ('4s', 1.4977384448379325), ('ipod', 1.4966988373925263), ('4', 1.4776524801798216), ('touch', 1.3836936937733773), ('話題', 1.2830962460190283), ('使える', 1.267703173083845), ('用', 1.2650386013010513), ('向け', 1.26418467742026)] ppmi [('ipod', 0.2859661921087914), ('ipad', 0.24883286298039248), ('4s', 0.2447535806470899), ('touch', 0.2349337206345609), ('第4世代', 0.22949601240870882), ('3gs', 0.18854934562128067), ('4', 0.15223633417263555), ('ios', 0.14752415366324956), ('第3世代', 0.14382973978764851), ('据え置く', 0.13690344251866945)] svd [('売れ筋', 0.07950519361803438), ('touch', 0.07289990333758399), ('ガイガーカウンター', 0.0720546914668142), ('ipod', 0.06996932998910954), ('お浚い', 0.06655078247840501), ('ホルダー', 0.06373112962844232), ('電子書籍', 0.06339235714445059), ('スタンド', 0.062353061811765656), ('計測', 0.06080525440724401), ('ゲーム機', 0.06062771603307594)]
パラメータ最適化とかは以下の論文を参照のこと
参照
- ダヌシカ・ボレガラ.ウェブデータの機械学習.講談社,2016.p. 192.
- glove-python
- Making Sense of Word2vec
■
導入
klis14のしんさく (@lapis_zero09) | Twitterです.
この記事は,klis advent calendar 2016の23日目の記事です.
今日からクリスマス三連休ですね.
昨日は
本題
財布の膨らみ
突然ですがこれはなんでしょう.
そう筑波大生なら誰しもが持っている学生証ですね.
学生証の使い所は,身分証,筑波大附属図書館の入館・貸与証,コピー機での認証,各証明書・旅客運賃学生割引の発行などがあります.
人によってはあまり使わない機能もあるかもですね.
この機能を実現しているのは裏面のバーコードあるいは内蔵されているICチップです.
詳しく知りたい方はSony JapanのWebページ*1*2*3を御覧ください.
有益
せっかく財布に入れて持ち歩いているのですから,もっと有益に使いたいですね.
学生証のICチップはクレジットカードのように剥き出しなものではなく,完全に内蔵されているタイプであり,非接触型のICカードリーダを用いて内容を読み込むことができます.
非接触ICカードリーダには以下のようなものがあります.
このカードリーダとnfcpy*4を用いることで学生証のICチップを読み取ることができます.
Python module for near field communication — nfcpy 0.13.4 documentation
nfcpyのインストールについては割愛します.
nfcpyのexampleであるtagtoolを用いて以下のように学生証のID,PMM,SYSを取得することができます.
IDは製造ID(IDm)のことで8バイトのバイト列です.上位2バイトの値が製造者コード,続く6バイトがカード識別番号です.
PMMは製造パラメータのことで,こちらも8バイトのバイト列です.これはカードの種別および性能を識別するためのパラ メータです.
SYSはシステムコードのことで,システムを特定するための2バイトの値です.
また,Type3とありますから学生証は「JIS X 6319-4」に準拠したソニーのFeliCaをベースとしていると認識されています.
さらに,筑波大学の学生証は裏面にロゴがある通り,FCFフォーマット*5です.
ここ*6には,FCFキャンパスカードフォーマット仕様*7に準拠したものとありますね.
有効活用したい
klisの研究室の入室には学生証とは別のICカードが必要です.
どうせなら学生証で入れるようにしてほしいというのは誰しもが思うことですね.
いきなり研究室に設置するのは色々問題がありそうなので,筆者のマンションでデモを行います.
まず,先ほどのICカードリーダに加え,みんな大好きRaspberry Piとサーボを用意し,繋ぎます.
サーボはGWSサーボ GWSMIRMGFA(MICRO/2BBMG/FP) フタバ: パーツ一般 秋月電子通商 電子部品 ネット通販です.
サーボの操作はServoBlasterを用いて行うことができます.
nfcpyとカードリーダで取得したパラメータを照合し,合致すればサーボを回転させるというプログラムを適当に書きます.
これをドア鍵に設置することで学生証をかざすことでサーボでサムターン*8を回転させ,開閉することが可能です.さらには,10秒後には鍵が閉まるオートロック機能も付与しています.
不要時には電圧がかからないので,本来の鍵を鍵穴に差し込み開錠・施錠も可能です.
懸念事項として,ドアからPaSoRi RC-S380が生えている御宅が少ないので住居を特定される可能性があります.
しかし,これはあまり問題にはなりません.
なぜなら,本来の目的は我が家の鍵を開閉することではなく,研究室の認証方式を変換することだからです.
数日後,B3の初ゼミが研究室で行われました.
完
明日はhimktさんです.期待しましょう.
参考
*1:"Sony Japan | FeliCa | 法人のお客様 | ダウンロード"."Sony Japan". http://www.sony.co.jp/Products/felica/business/tech-support/index.html.
*2:"Sony Japan | FeliCa | FeliCaとは | FeliCaって何?"."Sony Japan".https://www.sony.co.jp/Products/felica/about/index.html.
*3:"Sony Japan | FeliCa | NFCについて | NFCの定義"."Sony Japan".https://www.sony.co.jp/Products/felica/NFC/index.html.
*4:"Python module for near field communication — nfcpy latest documentation".nfcpy.http://nfcpy.readthedocs.io.
*5:"一般社団法人 FCF推進フォーラム".http://fcf.jp/index.html.
*6:澤村 博道."情報科学類・CS専攻入退室管理システム".http://www.tech.tsukuba.ac.jp/2010/report/n14_report2010.pdf.
*7:"FCFキャンパスカードとは"."一般社団法人 FCF推進フォーラム".http://fcf.jp/fcf12461125151253112497124731245912540124891239212399.html.
*8:"図解 - 鍵の各部名称|鍵と防犯の用語集|住まいの防犯特集"."美和ロック株式会社".http://www.miwa-lock.co.jp/lock_day/glossary/lock/12.html.
cowrieを設置した
cowrie
cowrieインストール
cowrie用設定
自分がcowrieを設置している環境はdebian ver8.5.
以下コマンドで必要なものをインストール.
# apt-get install git python-dev python-openssl openssh-server python-pyasn1 python-twisted
cowrieが22番ポートを使うので普段自分がsshするポートを指定できる範囲で変える.
sshd_configのバックアップを取った上で書き換える.
# vim /etc/ssh/sshd_config Port 22 ↓ Port {任意の番号}
書式のテストをして,いい感じならsshd_configの再読み込み.
# sshd -t # service sshd restart
cowrie設置用のユーザを作成し,22番ポートをcowrie用に設定.
# adduser --disabled-password cowrie # iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22 -j REDIRECT --to-port 2222
cowrieにユーザをスイッチ.
# su cowrie $ cd
cowrieのインストール
cowrieをダウンロード,設定ファイルを作る.
$ git clone https://github.com/cowrie/cowrie.git $ cd cowrie $ cp cowrie.cfg.dist cowrie.cfg
設定ファイルをいじる(ここではホスト名だけを変えた).
$ vim cowrie.cfg hostname = {任意のホスト名}
cowrieの設定ポートを直接22にしてauthbind使ってもいい.
# apt-get install authbind # touch /etc/authbind/byport/22 # chown cowrie /etc/authbind/byport/22 # chmod 777 /etc/authbind/byport/22
cowrie/data内にあるuserdb.txtいじれば, 攻撃者がログインできるユーザネームとパスワードのコンビを変えることができる.
cowrieの起動
下記コマンドで起動&起動できたか確認.
$ ./start.sh $ cat cowrie.pid #process or $ netstat -antp | grep 2222
cowrieに接続してみる
$ ssh root@{ipaddress}
userdb.txtで指定したユーザネームとパスワードのコンビでログインできたらok.
cowrie側でlogの確認
自分のssh用に開けたポートでログインしたらlogを見る.
$ cat ~/cawrie/log/cowrie.log
攻撃者のipとか見える.
cowrieを止める時はstop.shとか
以上cowrieのインストール.
kippo-graphのインストール
kippo-graphはkippoで取れた攻撃者情報をいい感じに可視化してくれるやつ.
cowrieでも使えるっぽいので使っていく.
cowrieで取れたデータをMySQLに保存して,phpで表示するというもの.
MySQLのインストール
MySQLをインストール.
# apt-get install mysql-server python-mysqldb
インストール途中でMySQLのrootのパスワードを聞かれるのでいい感じに設定.
MySQLにcowrie用のユーザを追加と権限を設定.
# mysql -u root -p #インストール途中に入力したrootパスワードを入力 mysql > create user 'cowrie'@'localhost' identified by '{cowrieのパスワード任意で}'; mysql > grant all on cowrie.* to 'cowrie'@'localhost' identified by '{cowrieのパスワード}'; mysql > exit;
cowrieにスイッチして,データベースをいい感じにしていく.
# su cowrie $ cd ~/cowrie/doc/sql/ $ mysql -u cowrie -p mysql > create database cowrie; mysql > use cowrie; mysql > source mysql.sql; mysql > show tables; +-----------------+ | Tables_in_kippo | +-----------------+ | auth | | clients | | downloads | | input | | sensors | | sessions | | ttylog | +-----------------+ 7 rows in set (0.00 sec) mysql > exit;
cowrieのログの出力を今しがた作ったデータベースにガンガン入れていくように設定する.
$ vim ~/cowrie/cowrie.cfg ~略~ [database_mysql] host = localhost database = cowrie username = cowrie password = {cowrieのパスワード} port = 3306 ~略~
kippo-graphのインストール
# apt-get update && apt-get install -y libapache2-mod-php5 php5-mysql php5-gd php5-curl # /etc/init.d/apache2 restart
最新版をダウンロードしてやる. (2016-08-15現在 Ver. 1.5.1)
# cd /var/www # wget http://bruteforce.gr/wp-content/uploads/kippo-graph-1.5.1.tar.gz # openssl sha1 kippo-graph-1.5.1.tar.gz # tar zxvf kippo-graph-1.5.1.tar.gz # mv kippo-graph-1.5.1 kippo-graph # cd kippo-graph # chmod 777 generated-graphs # cp config.php.dist config.php # vim config.php ~略~ define('DB_HOST', 'localhost'); define('DB_USER', 'cowrie'); define('DB_PASS', '{cowrieのパスワード}'); define('DB_NAME', 'cowrie'); define('DB_PORT', '3306'); ~略~
ブラウザでhttp://{ipaddress}/kippo-graph/を見る.
余談
kippo-graphにはKIPPO-PLAYLOGという機能があり,攻撃者がログインしてから,ログアウトするまでの実行コマンドを可視化してくれる機能がある.
cowrieではバグで今んとこ(2016-08-15現在)使えないっぽい https://github.com/ikoniaris/kippo-graph/issues/44
スクリプトを実行すれば見れる.
$ cd ~/cowrie/log $ python ../../bin/playlog {任意のlog}.log
kali linux rolling edにvirtualboxを入れるときに躓いたこと
kali linux rolling
dpkg -i {virtualbox...}.deb
エラー吐いたら
# sudo apt-get install -f
->依存環境が解決されずインストールできない
->aptでインストールしてみる
https://www.virtualbox.org/wiki/Linux_Downloads ここを参照して
# vim /etc/apt/source.list
以下を追加
deb http://download.virtualbox.org/virtualbox/debian xenial contrib
環境によって'xenial' を'vivid', 'utopic', 'trusty', 'raring', 'quantal', 'precise', 'lucid', 'jessie', 'wheezy', 'squeeze'で入れ替える
source.listに追加した に対してのkeyを追加する
# wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add - # wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add -
fingerprintがちゃんと合ってるかapt-key fingerprintで確認
ちなみに2016/05/20時点で正しいのは以下
The key fingerprint for oracle_vbox_2016.asc is B9F8 D658 297A F3EF C18D 5CDF A2F6 83C5 2980 AECF Oracle Corporation (VirtualBox archive signing key) <info@virtualbox.org> The key fingerprint for oracle_vbox.asc is 7B0F AB3A 13B9 0743 5925 D9C9 5442 2A4B 98AB 5139 Oracle Corporation (VirtualBox archive signing key) <info@virtualbox.org>
そして以下を実行
#apt-get update # apt-get -y install virtualbox-5.0 パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 インストールすることができないパッケージがありました。おそらく、あり得 ない状況を要求したか、(不安定版ディストリビューションを使用しているの であれば) 必要なパッケージがまだ作成されていなかったり Incoming から移 動されていないことが考えられます。 以下の情報がこの問題を解決するために役立つかもしれません: 以下のパッケージには満たせない依存関係があります: virtualbox-5.0 : 依存: libpng12-0 (>= 1.2.13-4) しかし、インストールすることができません 依存: libssl1.0.0 (>= 1.0.0) しかし、インストールすることができません 依存: libvpx1 (>= 1.0.0) しかし、インストールすることができません 推奨: libsdl-ttf2.0-0 しかし、インストールされようとしていません 推奨: dkms しかし、インストールされようとしていません 推奨: linux-headers しかし、インストールすることができません E: 問題を解決することができません。壊れた変更禁止パッケージがあります。
やっぱりダメ
しかし,
#apt-get libpng12-0
とかやってもないと言われるので,
手動でパッケージをインストールする.
自分のアーキテクチャにあったdebファイルをダウンロードする(上のエラーで依存になっているもの)
筆者はamd64なので以下の3つ
libpng12-0 - https://packages.debian.org/jessie/amd64/libpng12-0/download
libvpx1 - https://packages.debian.org/jessie/amd64/libvpx1-dbg/download
libssl1.0 - https://packages.debian.org/jessie/amd64/libssl1.0.0/download
それぞれパッケージをダウンロードしたらmd5, sha1, sha256でチェックサム確認
# md5sum lib* 2f392ddcfd7de95cd794b8c5433e272b libpng12-0_1.2.50-2+deb8u2_amd64.deb 57c3d82c10706d711f21c03f34d8249c libssl1.0.0_1.0.1e-2+deb7u21_amd64.deb a31e1de3bf7d71b02763c7eb194a445f libvpx1_1.3.0-3_amd64.deb
合致したら以下でインストール
# dpkg -i libvpx1_1.3.0-3_amd64.deb libpng12-0_1.2.50-2+deb8u2_amd64.deb libssl1.0.0_1.0.1e-2+deb7u21_amd64.deb
そしてvirtualboxインストール
# apt-get -y install virtualbox-5.0
成功.
kali linux日本語入力環境がおかしくなった時の対処法
kali linux rolling
kali linux rolling editionで日本語入力環境がおかしくなった時にやったこと
uim
kali linuxはdebianベースのOSで日本語入力環境を整えるパッケージとしては,
uim, ibus, etc..あるが,他のサイトを参照してもuimを使ってるものしかない.
実際にibusを入れてみたが動かず...
anthy
また,辞書もanthy, mozc, etc..あるが, anthyしかうまく動かないっぽい.
mozcはguiを起動させようとしても起動せずそのまま落ちる状態.
uim uim-anthy
そこで,uim, uim-anthyのパッケージを入れて日本語入力環境を整える.
# apt-get install uim uim-anthy
が,uimとanthyを使ってもある設定をすると日本語入力ができなくなる.
やると日本語入力ができなくなる行為
以上の設定をやってしまうと,日本語入力ができなくなる.
この設定をやってしまった場合
チェックを外し(defaultを設定し),再起動する.
それでも日本語入力ができない場合は以下を実行.
# apt-get purge uim uim-anthy # apt autoremove
これでもまだダメな場合は,
# dpkg -l |grep "uim" # dpkg -l |grep "anthy"
それぞれで出てきたパッケージに対し,apt-get purge
を実行.
めんどい人は以下で
# apt-get purge `apt list | grep -G "uim\|anthy" | cut -d"/" -f1 | xargs echo` # apt autoremove
そして,以下を実行.
# apt autoremove # reboot
そして,再インストール
# apt-get install uim uim-anthy
その他,設定を変えるたびにrebootするのが望ましい.
osインストールの時も日本語だとうまく表示されませんって出るし,
日本語対応が完璧ではないのかな(そりゃそうか)
kali linuxインストールから日本語化まで
kali linux
悪用しない
kali linux isoファイルのダウンロード
からkali linux 64bitをダウンロードする.
ミラーサイトの場合は,amd64が64bit
sha1sumを確認してマッチするかちゃんと確かめる.
# openssl sha1sum {kaliのisoファイル}
USBブート
今回はUSBからブートする方法
dmgに変換
kaliのisoイメージをdmgに変換.
kaliのisoがあるディレクトリで
# hdiutil convert -format UDRW -o kali.dmg kali-linux-2016.1-amd64.iso
USBのアンマウント
まず,USBのデバイスパスの確認
USBをささない状態で以下を実行
# diskutil
USBをさした状態で上記を実行
この時,新たに認識されたデバイスがUSBなので
diskN の N の部分をよく覚えておく.
以下で,USBをアンマウントする
# diskutil unmountDisk /dev/diskN
USBに書き込む
以下でUSBに書き込み(結構時間かかる)
# sudo dd if=kali.dmg of=/dev/diskN bs=1m
ここでパス違えるともれなく死ぬ
書き込みが終わったら以下のコマンドでUSBを取り出す.
# diskutil eject /dev/diskN
起動
USBを挿してインストールするPCを起動.
Thinkpadでは起動メディアを選択できるのでF12キーを押しながら起動.
この時うまく認識されなかったらBIOSの起動メディア順序を変えてみる(やり方は省略)
それでもダメならUSB書き込みのプロセスをもう一度.
うまくいったら
kali 2.0 sanaの場合
- Graphicalinstall を選択してEnter
- 言語の選択->「Japanese - 日本語」
- 国を選択->「日本」
- キーボードを選択->「英語」(自分の環境に合わせて)
- ネットワークの選択->デフォルトでok
- ドメイン名->「localhost」
- パスワード設定->任意のパスワード
- ディスクのパーティショニング->「ディスク全体」->USBじゃないHDDを選択->「すべての...」->「パーティショニングの終了とディスクへの変更の書き込み」->「はい」
- ネットワークミラー->「はい」
- プロキシ->デフォルトでok
- GRUBブートローダ->「はい」
- デバイスの変換->「/dev/sda」
- 「続ける」を選択
->勝手に再起動->ユーザ:root,パスワードでログイン
ログインできたら成功
kali rolling edition の場合
言語を日本語にしてインストールすると apt-get update upgrade
後に環境が壊れるバグ(?)が起きたので初期言語を英語にしといて後で日本語に設定する.
- Graphicalinstall を選択してEnter
- 言語の選択->「English」(?)
- 国を選択->「日本」
- キーボードを選択->「英語」(自分の環境に合わせて)
- ネットワークの選択->デフォルトでok
- ドメイン名->「localhost」
- パスワード設定->任意のパスワード
- ディスクのパーティショニング->「ディスク全体」->USBじゃないHDDを選択->「すべての...」->「パーティショニングの終了とディスクへの変更の書き込み」->「はい」
- ネットワークミラー->「はい」
- プロキシ->デフォルトでok
- GRUBブートローダ->「はい」
- デバイスの変換->「/dev/sda」
- 「続ける」を選択
->勝手に再起動->ユーザ:root,パスワードでログイン
$ dpkg-reconfigure locales
スペースで ja-JP.UTF-8 UTF-8
を選択->エンター
$ reboot
ログインできて日本語になってれば成功
こっからsanaもrollingも一緒
http://docs.kali.org/general-use/kali-linux-sources-list-repositories に従って,
$ vim /etc/apt/sources.list
以下を記載
deb http://http.kali.org/kali kali-rolling main contrib non-free # For source package access, uncomment the following line deb-src http://http.kali.org/kali kali-rolling main contrib non-free
以下を実行
$ apt-get update $ apt-get dist-upgrade
upgradeの方がうまくできなかったら
$ apt-get dist-upgrade --fix-missing
途中で日本語表記が崩れますがすぐに直る
直らなければ...
日本語入力環境
以下を実行
$ apt-get install uim uim-anthy $ reboot #再起動