アプリとサービスのすすめ

アプリやIT系のサービスを中心に書いていきます。たまに副業やビジネス関係の情報なども気ままにつづります

異常検知(変化検知)の詳細と特異変換スペクトルと動的時間伸縮法まとめ(機械学習)

異常検知とは、機械学習の一手法で、普通の値のデータの中から極端に大きかったり、小さい値の「異常」なデータを見つけ出すものだ。


異常検知の用途で有名どころは巷では以下のようなものがメインらしい  

 

マーケティング =>流行のブレイクの検出
コンプライアンス  =>情報漏洩/不正検知
・製造系   =>不具合発生検知
・機械系  =>故障検出
・システム運用系  =>障害検出
・ネットワーク運用系  =>トラフィック異常検出
・WEB系  =>トピック潮流変化検出
・セキュリティ系  =>攻撃・侵入検出(コンピュータウィルスDOS攻撃
・サイバー犯罪に使うやつ=>情報潮流、なりすまし


いずれも普通じゃないデータとか、珍しいデータを検出するものだ。


異常検知の3種類
異常検知は主に3つのタイプに分かれる。機械学習シリーズの書籍とかに詳しく載ってるので、ここでは簡単に触れとく。


まず触れておきたいのは異常検知で扱うデータには「定常データ」と「非定常データ」がある。異常検知ではこの2つで使う手法が異なる。
定義は以下の通り


定常データ:同じ波形が続くような時系列データや、統計的にデータ分布図が正規分布(山が一つの単純な曲線)になる


非定常データ:同じ波形が続かない時系列データや、統計的なデータ分布図が正規分布にならない(山が2つ以上の曲線)


・外れ値検知
すでに持ってる(既存の)データから異常なデータや異常箇所を割り出す手法。
正常データと異常データの割合→99:1


くらいのデータ、つまり正常データがほとんどで異常データ少ししかないデータが対象になることが多い。


外れ値検出のほとんどのアルゴリズムは定常データを扱う。
その時は、マハラノビス距離で求められるアルゴリズムに限定させることが多い。代表的なものに、k-means、ランダムフォレスト、one class SVMなどがある

 


・変化検知
これは主に定常/非定常な時系列データなどに多く使うもので、データが大きく変化する点を検知する。googleである「急上昇ワード」が好例だ。扱うデータは非定常データであることが多い。


変化検知で、非定常データを扱うときのアルゴリズムには、いろいろある。メジャーなのは
・特異変換スペクトル
・動的伸縮法
・LSTMなどの時系列を予測するアルゴリズム


などを使うケースが多い。


・異常行動検知
これは多くのユーザーと違う行動をとるユーザーを検出するときに使う。
手法としては、同じ行動をとる多くのユーザーの行動を統計的に確率分布でパターン化し正常データとして扱う。逆に、その確率分布のパターンと異なる分布のデータになるユーザーを異常行動をしたユーザーとみなし、検出する。
ググるとLSTMとかがよく使われてる。

 


特異変換スペクトル(Singular Spectrum Transformation :SST)について

特異変換スペクトルは主に非定常データにおける異常部位の検出に使う(もちろん定常データにも使える)


特異変換スペクトルは、非定常データでもデータが大きく変化してる点(異常箇所)を検出できる。訓練データやテストデータはいらず、検出したいデータだけ用意すれば、numpyで簡単に実装できる
詳しい数式や論理とかは専門書や論文に任せてここではコードで実装みる。


まず検出したいデータは約半年分の検索ワードを2つ(AとB)を取り出して、特異変換スペクトルにかけてみた。

ワードA、Bの可視化

ワードA
f:id:trafalbad:20180809154943p:plain


ワードB
f:id:trafalbad:20180809155015p:plain


 
特異変換スペクトルのメイン実装コードは以下のようになる。ついでに結果を可視化した。

 

from sklearn.preprocessing import MinMaxScaler
 
mss=MinMaxScaler()
train1_frame=pd.DataFrame(mss.fit_transform(df_train1))
train2_frame=pd.DataFrame(mss.fit_transform(df_train2))
 
defembed(lst,dim):
emb=np.empty*1
emb=np.append(emb,tmp,axis=0)
returnemb
 
train1=np.array(train1_frame[0],dtype='float64')
 
w=168# 部分時系列の要素数
m=2# 類似度算出に使用するSVDの次元数
k=int(w/2)# SVD算出に用いる部分時系列数
L=int(k/2)# # 類似度を比較する2つの部分時系列群間のラグ
Tt=train1.size
anomaly_score=np.zeros(Tt)
 
# 異常値のスコアを算出するメソッド
score_list=[]
fortinrange(w+k,Tt-L+1+1):
tstart=int(t-w-k+1)
tend=t-1
# t以前の部分時系列群
X1=embed(train1[tstart:tend],w).T[::-1,:]
# 異常度算出対象の部分時系列群(test matrix)
X2=embed(train1[(tstart+L):(tend+L)],w).T[::-1,:]
 
# X1にSVDを行い上位m次元を抜き出す
U1,s1,V1=np.linalg.svd(X1,full_matrices=True)
U1=U1[:,0:m]
# X2にSVDを行い上位m次元を抜き出す
U2,s2,V2=np.linalg.svd(X2,full_matrices=True)
U2=U2[:,0:m]
 
# U1とU2の最大特異値を取得
U,s,V=np.linalg.svd(U1.T.dot(U2),full_matrices=True)
sig1=s[0]
 
# 最大特異値の2ノルムを1から引くことで異常値を得る
anomaly_score[t]=1-np.square(sig1)
score_list.append(anomaly_score[t])
 
 
score_=np.reshape(score_list,(len(score_list),))
 
# 変化度をmax1にするデータ整形
mx=np.max(score_)
score_=score_/mx
 
# trainデータの異常部位plot
train_for_plot=np.array(train1_frame[0],dtype='float64')
fig=plt.figure()
ax1=fig.add_subplot(111)
ax2=ax1.twinx()
 
p1,=ax1.plot(score_,'-b')
ax1.set_ylabel('degree of change')
ax1.set_ylim(0,1.2)
p2,=ax2.plot(train_for_plot,'-g')
ax2.set_ylabel('original')
ax2.set_ylim(0,12.0)
plt.title("Singular Spectrum Transformation")
ax1.legend([p1,p2],["degree of change","original"])
plt.show()

 

ワードA
f:id:trafalbad:20180809155034p:plain

ワードB
f:id:trafalbad:20180809155048p:plain


 
ご覧の通りAでは1カ所で急上昇し、Bは数カ所でデータが変化してる。いずれも非定常データだが上手く検出できてる。


数値も大きく変化してる点で

・Aが10→80

・Bが800→1800

まで上昇しているから、適切に異常個所を検出できてるっぽい。



特異変換スペクトルの活用方法は個人的に

・異常部位の検出
・訓練データやテストデータのを分ける

のに使えた。

 


閾値の設定について


反対に変化点検出のときに、異常値を判断する「閾値」の設定は特異変換スペクトルでは難しかった。
スペクトル変換しているので、リアルの値とかなり変わっている。そのため、閾値設定には工夫が必要になる。


非定常データの閾値設定には
・動的時間伸縮法(Dynamic time warping:DTW)

・LSTMのような回帰アルゴリズムとMSEの組み合わせ

とかの方が一般的だ。


動的時間伸縮法(DTW)は複数の時系列データ同士の距離(類似度)を計算し、最も高い類似度 or 最も低い類似度の時系列をk個選び、その平均値から閾値を求める。kが大きく設定すると閾値も低くなる。閾値の設定はケースバイケースで設定する必要がある。


DTWのコードはここを参照してほしい。


結論、特異変換スペクトルは定常/非定常に関わらず、どんなデータでも、訓練データとテストデータを分けたり、異常部位を見つけるのに役に立つ。かつ簡単に実装できるので、異常検知では色々な用途に使えるので、オススメの手法だ。

 

大学編入試験の英語(英作文)、口頭試験の対策等、使える情報をまとめてみた

大学編入というと最近では、ネット上でも具体的な情報が出回ってきた。しかし、口頭試験や専門的な科目の情報はまだ少ない。今回は質問をもらったので、編入試験に役立つ情報として口頭試験について、英語の勉強法等、編入あるあるの質問に回答していきたい。

なるべく自分の体験や先輩から聞いた実体験を元に書いてある。なるべく質の高い回答がしたかったので、記事の構成から質問内容は少し変更してあるが、質問内容には全部回答してある。

f:id:trafalbad:20180204162005j:plain




Q1
編入の口頭試験の傾向と対策は?

大学によりけりだが、基本的な問題がほとんどで

・その場でホワイトボードが用意されて問題を解く

・基礎的な知識「ーの定理について説明しろ」を口頭で答えるやつ

とか色々あるようだ。口頭試験でプリントが配れるものは、試験ほど時間は与えられない。その時間内で解いた問題を試験管(教授)にわかりやすく口頭で回答を説明する形式が多いと思う。

例外的なものでは、院試だが、筑波大の知能機能システム専攻で、時間を大量に与えて、そのあと教授に前でプレゼンするっていう口頭試問のパターンがあった。

ともあれ本当に大学によりけりとしか言いようがないので、受ける所をネットでググってみたり、予備校で具体的な情報を仕入れた方が間違いない。


参考:口頭試験、面接の勉強法

ちなみに口頭諮問の勉強法では、

・教科書の例題レベルの問題リストを作る

・頭の中でその正解を自分の言葉で回答できるように考える練習をする

という勉強法があった。体験談だが、この勉強法で論理的な思考力が身につき、本番でもスムーズに回答できるようになるようだ。面接でも同じように質問リストを作ることで同じ練習ができる。参考までに




Q2
専門分野の勉強対策はどうやるの?


大学の教科書で編入試験で必要な基礎知識は身につく。ただし応用問題を解けるようになる必要がある。

基礎ができれば、あとはネット上で高専生や編入に合格した人が使ってる参考書や問題集がメジャーなので、それで問題を解いて思考力をつけれるのがオールマイティな勉強法といえる。

下位の大学は教科書の基礎知識と例題程度で解けるかもしれないが、難関大学は思考力が必要なので、ネット上でメジャーな問題集をやって思考力をつけよう。結果的に過去問が解ければいいのだ。

早い話、教科書で基礎が理解できるなら、あとは問題集をやればいい。基礎ができてて、応用問題に解ければ、過去問は解ける。




Q3
大学では高校のときのように教科書+傍用問題集等のようなものは購入するの?


大学編入も大学1.2年の内容を聞いてくるのは変わりない。大学では基本試験用に問題付きの教科書を購入する。むしろ高校のように編入のために教科書+問題集を購入することはない。

なので自分で編入用の問題集は別途購入する必要がある。高校のとき入試対策ができていても、大学教養課程は難しいし、教授も丁寧に教えてくれないので、どれだけ独学できるかによるだろう。独学ができれば編入も高校と同じ容量で勉強できる。

高校でも簡単な大学は基礎程度の内容を、難関大学は高校の内容でも思考力が必要なひねった問題を出してきたはず。

編入も同じで簡単な大学は基礎問題を、難関大学なら大学1.2年の内容で思考力が必要な問題を出してくる。基本的に高校は暗記重視だが、編入は思考力重視の問題が目立つ傾向がある。





Q4
英語の勉強に予備校は必要?


個人的な考えだが、過去問から対策が立てられれば、編入英語に予備校は必要ない。ただ勉強法または、何をすべきかわからないなら予備校に行った方が教えてくれるので、予備校に行く方がてっとり早いだろう。

過去問から対策を立てて、やることがわかるなら、予備校は過去問だけ手に入れるために利用すればいいと思う。



あと、個人的に編入英語は勉強法を知っておくことが何より有利だ。

英語は人により勉強法は異なるが、根本的な部分は同じで、人によってそのやり方が違うだけだ。

これは参考書ではないが英語の勉強法が詳しく載ってて、もちろん和文英訳の勉強法も載っている。

この本で勉強法を知っておけば、自分で考えて勉強法が構築できるので、まずは参考書に手をつける前にこの本で英語の勉強法について知っておくとかなり有利だと思う。編入の英語対策が立てやすくなる。






Q5
どの予備校がオススメ?


個人的に都心では河合塾KALSと中央ゼミナールを使ってる人が多いと思う。

もし東京に住んでるなら河合塾KALSか中央ゼミナールがオススメだ。なぜかというとネット上の評価もそれなりに高いし、二つは過去問が充実しかつ、実績もある。

しかし、個人的に言いたいのは塾は編入の情報、過去問を得たり、独学で勉強できない科目を補ったりするところであり、あくまで入るための道具に過ぎない。


編入の勉強は自分次第なので、塾に頼り切るよりも自分が勉強を能動的に進めることが非常に重要で、その上で予備校は補助的に使う程度に留めるべきだと思う。勉強は自分で考えて進めている人の方が受かっている傾向が強いのは高校も編入も同じ。

とはいえ人によりけりなので、塾は自分の好みに合わせて使って欲しい




Q6
編入の勉強時期は?


下の編入の勉強法の記事で書いているが、高校で理系出身か、文系出身かで勉強時期が変わる。

trafalbad.hatenadiary.jp


自分は独学でこんな感じでやった。あくまで自分のケースなので、参考程度に。

もし理系出身なら、だいたい1年生の9月くらいから1月くらいまで、基礎を徹底的にやり、2月から3月までが応用として問題集を解く時期。それ以降は過去問をやったり、過去問が解けるようになるまで基礎の反復や思考力を鍛えるのに費やすといいだろう。

まとめるとこんな感じ


1年生の9月〜1月 基礎固め

2月〜3月 応用問題を解く時期

2年4月以降 過去問をやったりする時期



塾の場合はもっとスケジュールもギリギリで詰め込む感じ。2年生で理系の編入なら早いにこしたことはないので、早めに自分なりの勉強法を確立して、余裕を持っておいた方が絶対にいい。




Q7
編入の英語勉強法(基礎編)はどうやるの?


編入の英語は大学によりさまざまだから対策も大学によるので決まった方法はないが、基礎固めは共通している。

英語はまず

・文法

・単語

を確実に固めよう。特に、文法は文法問題のためではなく、「英語をスラスラ読むため」に必要と考えよう。この二つをおろそかにしていると編入の問題は確実に解けるようにならない。

個人的におすすめなのが、

がおすすめ。

効率的な勉強法としては、上にあげた英文法の本を完璧に理解して、速読英単語必修編と上級編レベルがスラスラ読めるレベルまで鍛えることだろう。速単は英作文や和訳にも応用が効くので効率的。

ネクストステージのような類の参考書は、編入向けではないので、コスパの点で無駄が多いのでやらない方がいい。

速読英熟語は基礎的な熟語の把握、またはできたらやるくらいでいいだろう。

また英文解釈の本はたくさん出ているが、英文解釈(読解)に必要なのは基礎的文法の理解と、英文を読む力なので、編入の英語に別に英文解釈の本は必要ない。特に、英文解釈の本は英語に必要な文法を体系立ててまとめてないので、基礎的な英文法習得という点で効率的ではない。

あまり多くの参考書を買わず、これだと決めた参考書を徹底的にやったほうがいい






Q8
編入の英文和訳の勉強法はどうやるの?


和文英訳は英作文と同じ要領で勉強すればいい。まずは定型的な例文を覚えよう。これは「英借文」ともよばれている方法で基礎例文を覚えておけば、英作文を一から考えなくてよくなる。英作文は次の本をどちらかセットでやるだけで十分だと思う。


または




特に「竹岡広信の英作文〈原則編〉が面白いほど書ける本」は英作文をどう書いたらいいのかという考え方が載っているので、オススメだ。



また英作文は回答が決まっているわけではないので、自分で作った回答を添削してくれる人がいるとかなり有利。学校で英語に詳しくかつ、親切な講師に添削してもらったり、予備校を使うのもありだ。自分は留学生と仲良くなって添削してもらっていた。




Q9
編入に必要ない科目の単位について

編入で必要ない科目は単位が取れる程度で十分だ。最低限のことだけやって単位だけゲットし、あとは編入の科目に集中した方がいい。

また、単位の成績だが、編入の面接で聞かれることはほとんどない。理系編入は編入試験の成績がよければ受かる。つまり、基本的に大学の単位の成績はほとんど合否に関係ない。




Q10
大学編入成功のための心得&アドバイス




・あれこれ参考書に手をつけずこれだと決めたものをとことんやりこむ


応用問題よりも基礎固めを重要視しよう。特に高校の基礎知識は絶対に必要。編入は高校の延長なので、高校の基礎知識なしに編入で受かることはない。むしろ受かってる人は高校の基礎固めは十分すぎるほどやっている。



・自分の勉強法を確立させよう

編入試験で落ちる人で多いのは、勉強で何をやっていいのかわからない人だ。予備校でも言われたことを漫然とこなす人は受かってない。

それよりも試行錯誤して自分なりの勉強法を確立した人や、塾でもテキストに能動的に取り組んでる人が受かってるケースが非常に多い。高校で勉強法を知ってるなら、編入試験でもちょっと改良するだけで通用するだろう。

あくまで自分の体験だが、勉強を始める前に勉強法を知ることがかなり効率的だ。自分は勉強法を知るために、東大生とかの勉強法の本を片っ端から読んだ。そしてそれを試し、合わなかったら捨て、あったものがあったら自分なりに改良して使うを繰り返し、試行錯誤して勉強法を確立させてた。



・思考力を鍛えよう

基礎固めをやったら何かと発展問題を暗記してしまう人がいるが、編入試験は思考力がないと解くのが難しい。編入試験でよく使われている問題集で一問一問をじっくり考えよう。そうすることで思考力を鍛えられ、過去問が早く解けるようになる。

塾を利用するならテキストの問題をとことん考えて、思考力を鍛えることをオススメする。



・遊びも必要

編入試験はモチベーションを保つのがとても難しい。周りは遊んでる中、自分だけ勉強するというのはとてもきついからだ。そんなときは志望校に行ってみたりするのもありだが、適度に遊ぶことだ。

勉強だけやっていてモチベーションが維持できず、終盤で力尽きては意味ない。自分は勉強はもちろん遊ぶこともスケジュールに練りこんでた。ここら辺はドラゴン桜にも書いてある。





編入試験はホント大学によって形式は様々なのだが、勉強法の根本的な部分は変わらない。しかし、情報が足りなく、情報戦とはよく言われる。ネット上では手に入らない情報は予備校に行くのがてっとり早いだろう。この記事内容を参考にしたり、その他サイトを参考にして自分なりの対策を見つけて欲しい。



編入系記事
trafalbad.hatenadiary.jp

川田まみの全ベストシングル、アルバムを聴いた僕がオススメする良曲26選【シャナ系あり】

f:id:trafalbad:20160827153041j:plain
川田まみさんの曲はアニメ界では有名で、アップテンポ系からバラードまで心が動かされる曲ばかり。

川田まみは2001年から活動を開始し、音楽制作プロダクション「I’ve」のメンバーとして、アニメやゲーム関連の楽曲を多くリリース。2016年5月21日の「MAMI KAWADA FINAL F∀N FESTIVAL "F"」を最後に引退しました。

とても悲しかったのですが、残された名曲はどれも心に残るものばかりで、良質なインスピレーションをかき立ててくれます。今回は川田まみの曲を全曲聴いた自分が、その中からベストの26曲を選曲して紹介します
*個人的な好みが色濃く出てしまって、どの人にも好みが合うとは限りませんが、どれも自信をもってオススメできる曲構成にしたつもりです。

目次
クールでカッコイイ系
アップテンポ系
バラード系
聴いてて心地いい曲

クールでカッコイイ系

1. U/N

u/n

u/n

灼眼のシャナFinal Ⅲの15話の挿入歌。サビから徐々に盛り上がり、曲の1番のクライマックスの場面でアニメにぴったりのカッコイイシーンを想起させる。灼眼のシャナのオープニングと一緒に見ても鳥肌ものですが、個人的には漫画の「ハンターハンター」のシュールな場面をこの曲を聴きながら読むのが最高です。川田まみさんの中で1番好きな曲の1つ。



linkage

linkage

linkage


『LINKAGE』は、川田まみの3作目のオリジナルアルバムの中の一曲。曲自体は切ない流れになってますが、その中に含まれるサビのシュールさ、かっこよさは秀逸。なぜアニソンにならなかったのか不思議なくらいです。個人的には漫画「ONE PIECE」の新世界、パンクハザード編と合わせて読むのが好き。カッコいいバトル漫画との相性は抜群です。



PSI-missing

PSI-missing

PSI-missing


PSI-missing』とは、川田まみメジャー6thシングルで、アニメ『とある魔術の禁書目録』オープニングテーマ。タイトルを和訳するなら「サイ消失」でこれは超心理学(超能力、超常現象)の用語。曲自体はアニソンに抜擢されるだけあってクオリティも抜群です。始めからかっこいいテンポで始まり中盤のサビでかっこよさは最高潮になります。曲自体はかなり川田まみの中でレベルが高い方だと思います。





parablepsia

parablepsia

parablepsia


川田まみ 5thアルバム「PARABLEPSIA」
の一曲。序盤は曲としてのインパクトは弱めですが、1:17秒からの「回りめぐる世界〜」から突然カッコよくなります。アルバム「PARABLEPSIA」の中では代表曲であり、個人的にかなりの名曲の部類に入る。全体として盛り上がりは少なく、サビでクールに決めるところが特徴といえます。




serment

Serment

Serment


表題曲の「Serment」は、テレビアニメ『灼眼のシャナⅢ-FINAL-』の後期オープニングテーマ。動画で見れば分かる通り、切ない⇨カッコいいという流れで、アニメの映像との相性は抜群。数の多い川田まみの曲の中で、アニメのオープニングに選曲されるのはかなりユーザーからの支持率は高いのが特徴です。「sermant」はアマゾンレビューでも抜群の支持率でした。



going back to square

Going back to square one

Going back to square one


2012年8月8日にジュネオン・ユニバーサル・エンターテイメントジャパンより発売された川田まみの4枚目のオリジナルアルバム『SQUARE THE CIRCLE』の一曲。中盤のサビはシュールに決める流れで、全体的にテンポの良いリズムとカッコいいメロディが融合しています。個人的にこちらも数ある川田まみの曲の中で、アニメに起用されてもおかしくないレベル。



Enchantress

Enchantress

Enchantress


TVアニメ「ヨルムンガンド」OPテーマ。序盤はテンポの低いメロディが流れますが、中盤から一気にカッコよくなります。特に 1:14秒からの「胸を突く雷鳴〜」の部分がクールでカッコよく、アニメのオープニングと見ると鳥肌もの。収録アルバム「PARABLEPSIA」の中ではかなりクールな面でいい曲の部類に入ります。





HOWL

HOWL

HOWL


「CRブラックラグーン2」テーマソング。タイヨーエレックのパチンコ機『CRブラックラグーン2』のテーマソングとしてアルバム『parablepsia』でCD化された。序盤から容赦なく、カッコイイテンポで曲が展開していきます。中盤からテンポが早くなり、テーマソングとしてはかなり相性がいい。収録アルバム『parablepsia』はかなり川田まみの曲では名曲が多く、このHOWLもその中で名曲の1つだと思います。


TRILL

TRILL

TRILL

川田まみ、2年ぶりとなる待望の2ndアルバムSAVIAに収録。序盤からじょじょにテンポが上がっていくが、全体としてとてもクールな曲。パドル漫画のシュールなワンシーンがピッタリです。個人的にはテニプリの全国大会仁王戦vs不二戦のときに聴くのが好き。






masterpiece

masterpiece

masterpiece


ロックテイストと打ち込みを多用したデジタルサウンド、エフェクトの使用、途中にコーラスがあるといった複雑な曲構成は、「科学」と「魔術」が交錯する『とある魔術の禁書目録』の世界観や登場キャラクターの全体的な複雑さをイメージしたものとのこと[2]。「masterpiece」は、テレビアニメで使用される以前の2008年12月末頃より、『とある“ラジオ”の禁書目録』、『井口裕香の超ラジ!Girls』などで先行オンエアされていた。



CLIMAX

CLIMAX

CLIMAX

linkageに収録されている曲。どちらかといえばちょっとテンポ低めだが、シュールな部分は特に際立っている。サビの部分から一気に盛り上がるのが一番印象に残ってます。1:03からのサビの一気に盛り上がるところが印象に残る曲。




アップテンポ系


緋色の空

緋色の空

緋色の空


川田まみの2枚目のシングル収録曲。テレビアニメ『灼眼のシャナ』の前期オープニングテーマとして制作された楽曲。言うまでも無いですが、アニメに選曲されるということは名曲でユーザーの支持率も高いです。

アニメのオープニングのスピード感と、曲のスピード感のマッチングは絶妙。全体的なアップテンポ調が強く出ていて、盛り上がらずにはいられない一曲。





Break a spell

Break a spell

Break a spell


TVアニメ「東京レイヴンズ」新EDテーマ。序盤からだんだん盛り上がり、中盤のサビで、もっともヒートアップする構成になっています。「東京レイヴンズ」は若年齢層向けのライトノベルで「Break a spell」のテンポとは相性抜群。実はカラオケで歌いにくい。個人的に漫画「食戟のソーマ」の秋の選抜のシーンとのマッチングが気に入ってます。




JOINT

JOINT

JOINT


川田まみの5作目のシングル収録曲。 2007年10月31日のテレビアニメ『灼眼のシャナII』前期オープニングテーマ。『灼眼のシャナ』系の曲はアップテンポで、それに起用される川田まみの曲もまたアップテンポです。アップテンポでもかっこよさがにじみ出て、聴いてるだけで盛り上がること間違いなし。テンポの早いバトル漫画を読みながら聴くと、臨場感がアップしますよ。



Eager eyes

Eager Eyes

Eager Eyes


アルバム「PARABLEPSIA」収録曲。ユーモラスなメロディからアップテンポ展開する構成。1:03秒から特に盛り上がる展開に。アニメ『灼眼のシャナ』系の曲と比べて、若干テンポは劣るものの、充分アンプテンポといえる名曲です。




I civilization

I...civilization

I...civilization

アルバム「PARABLEPSIA」(作曲:高瀬一矢、編曲:HARD STUFF) に収録されている曲。序盤はとてもテンポが低くから始めるが、じょじょにテンションが上がる。


「PARABLEPSIA」は全アルバムの中でとてもいいタイプだと思います。曲はどちらかといえばクールな方だけど、とても澄んでいるのにテンションが上がる曲。



バラード系


悲しみの森

悲しみの森

悲しみの森


2006年3月、川田まみの1作目のオリジナルアルバム『SEED』の収録曲。バラードとはいえ、要所にカッコイイ要素の入る川田まみの曲の中では最も純粋なバラード。神秘的ともいえるそのメロディは、感傷に浸りたいときにはグッド。1:46秒の「深くなるこの傷口をさらに深く〜」の部分が、曲の中で最も純粋なバラードだと思います。





see visions

See visionS

See visionS


とある魔術の禁書目録Ⅱ」のオープニングテーマ。序盤では怖いイメージの曲が流れますが、サビからアニメのオープニング映像にぴったりのバラード調になります。特に第2サビからは、アニメのオープニングでは聴けないような勇気づけられるような曲調になっています。


言葉、心の声

言葉、心の声

言葉、心の声


linkageのCDに収録されている曲。バラードの中でも多分ベスト3に入る曲調。雨の日に聴いたり、物思いにふけるときに聴く曲に抜群。サビからの「今その胸の〜」部分が一番その部分が強調される。

序盤からバラードとわかる曲で全体にわたりそれが一貫してる。聴き終わった後にとても気持ちいい。



PIST

PIST

PIST


アルバム「PARABLEPSIA」収録曲。序盤に重低音の曲から、中盤のテンポの早いバラードに展開していくのが特長。川田まみの中では、かなり平凡なバラードと言えるかもしれません。若干カッコいい要素が入っているのですが、全体的にバラード調なのでバラード系に分類しました。


in answer

in answer

in answer

川田まみの3作目のオリジナルアルバム『LINKAGE』に収録されている。バラードというか曲のタイプを分けづらいが、シュール&バラードという感じ。サビのあたりが一番盛り上がるが、サビ前の方が個人的に好き。



Replica_nt

Replica_nt

Replica_nt


川田まみの5作目のシングル収録曲。序盤は平凡な流れですが、バラードとしての味が出てくるのは1:30秒あたりからです。川田まみのバラード系としては落ち着いていて、他のバラード曲とは若干、趣が違う曲となっています。個人的には「一回で曲の良さがわかる」というより、「何回か聴いてるうちにわかる」タイプの曲でした





another planet

another planet

another planet


川田まみの2枚目のシングル『緋色の空』収録曲。0:45秒「ほほえむ満月〜」からバラード調が絡みはじめ、2:03秒の「遥か遠くへ〜」からバラードとしては最も静かで最高潮になります。川田まみの曲としてはカッコイイ要素がなく、全体的な切ないメロディ構成の典型的なバラードですね。




聴いてて心地いい曲

TOY

TOY

TOY

『LINKAGE』(リンケイジ)に収録されてる曲。シュールでもアップテンポでもないが聴いてて悪くない。序盤からは曲調がわかりにくいだが、サビから本調子になってくる。

聴いた後に気持ちよくなる曲なので良曲に分類しました。




radiance

radiance

radiance

アニメ『スターシップオペレーターズ』のオープニング・テーマ、エンディング・テーマを収録したシングルの一曲。2005年2月23日に発表された1stシングル「radiance」。とてもクールな曲だが、カッコいい。曲の中では端っこの存在っぽいと思いきや聴いてみて全然悪くない一曲。




live a lie

live a lie

live a lie

SQUARE THE CIRCLEに収録されている一曲。とてもカッコいい曲でスピード感、テンポともに悪くない。曲全体の統一感が素晴らしく、シャナ系と違うタイプの名曲。

サビの前やサビに入ってからもとても澄んでる。個人的にナルトのラストバトルシーンに聴くのが一番好き。






川田まみの曲は今後リリースされることはないので、備忘録がてらまとめてみました。他のアーティストも良曲が多いので、機会があればまとめてみたいと思います。

DCGANで生成した訓練画像を使ってCNNで画像分類してみた【Deep learning】

以前からDCGANで生成した画像でデータセットを作ろうと思い、画像生成をしていたが、ようやくそれっぽい画像ができた。


f:id:trafalbad:20171028214149p:plain

今回はDCGANで作成した画像を「訓練画像」に、DCGANに食わせた元画像を「テスト画像」にして、CNNで分類してみることにした。CNNは以前、VGGNetモデルのCNNで画像分類したやつを使用。
「DCGANで作成した画像は、データセットに使えるのか」という試みで、その結果を書いていきたい。

trafalbad.hatenadiary.jp


目次
・全体の行程
・DCGANで訓練画像生成
・CNNでテスト画像分類


全体の行程
まず全体の作業行程のポイントは次の通り



・523枚のマンションの外観画像(外から見たマンションの建物の画像)を増幅した34860枚を、DCGANに読み込ませ画像を生成


・生成画像の中から、よさげな画像7040枚を訓練画像に採用


・DCGANに読み込ませた元画像523枚をテスト画像にする


・DCGANで生成した訓練画像をCNNで学習、テスト画像を分類できるか試す




これが全体の行程だ。CNNは以前、VGGNetを参考にマンション画像分類をしたものを使用し、それに今回新しく作った「マンションの外観」の訓練画像とテスト画像をプラスして、新たに正解率を評価する。

上手くいけばDCGANはCNNのデータセットも作れることの証明になる。

けど、結論から書くと上手くいかなかった。今回はそれをまとめていこうと思う。




DCGANで訓練画像生成


画像の用意

今回、生成するのは「マンションの外観」画像。元画像はGoogle画像から収集し、それを増幅。

増幅させるやり方は前の記事で書いてるので、それをそのまま使用し、523枚から31360枚に増幅。特に”角度変換”を何回も使った。

f:id:trafalbad:20171028215445p:plain



あとはDCGANにかけるだけ。最初、jupyter用のDCGANコードを書いたんだけど、broken pipeが出てカーネルが死ぬとまた最初からやり直しになるので、全くメリットがなかった。

なので普通にローカルで作成するものを作った。




作成画像

48エポック(だいたい34800ステップ)ほど回してできた画像がこちら。だいたい100ステップごとに冒頭に貼ったような1枚64pxの8×8=64枚、512pxの塊がフォルダに保存されていく。

f:id:trafalbad:20171028215711g:plain



ほぼ外観とそっくりなのでいいできだと思う。ただアップで見るとクレヨンで描いたような画質なので、元画像と比べてドット感がないのが少し気になる。


f:id:trafalbad:20171028214218j:plain



生成画像の中から、よさげな画像を別のファルダに入れていった。だいたい60枚くらいたまったら、この512pxの塊を単一の64pxの画像にバラす。



DCGANの訓練が終わってから画像を生成してもいいんだけど、訓練後に生成すると全て同じ画像になってしまうので、訓練途中にできた中から、出来のいいのを採用。


64枚、512pxの塊は下のコードで一気に分解できる。
64枚の塊画像をまとめて保存したファルダパスと、分解した画像を保存するファルダパスを指定して実行すれば、勝手に保存されていく。

import os
import sys
import scipy.misc
import cv2, matplotlib
import numpy as np


path_restore="DCGAN生成画像のフォルダパス"

path_save='分解画像保存先のフォルダパス'
images = os.listdir(path_restore) # 画像の読み込み


rows = []  # 横に分解
for i in images[1:]:
       rows.append(np.hsplit(cv2.imread(path1+'/'+i),8))


tin=[] # 縦に分解
for idx in range(len(rows)):
    for sec in rows[idx]:
        tin.append(np.vsplit(sec,8))


count=0
for idx in range(len(tin)):
    count+=1
    for sec in tin[idx]:
        count+=1
        scipy.misc.imsave(path_save+'/split{:04d}_{:02d}.jpg'.format(idx, count), sec)

こうして、CNNに読み込ませる訓練画像、約3520枚ができたので、”左右反転”をかけ、増幅して7040枚に。あとはDCGANに読み込ませた画像(増幅前)の元画像523枚をテスト画像にして、CNNで上手く判別できるかを試す。




CNNでテスト画像分類

訓練画像とテスト画像

さっきも書いたけど、


テスト画像 → DCGANに読み込ませた訓練画像(増幅前)の元画像523枚

訓練画像 → DCGANからできた画像の中から、出来のいいやつを分解した7040枚

にした。


CNNは前にマンション関連の画像を判別するために、あらかじめ作ってあるやつを使う。そのときのラベル0〜3の訓練画像とテスト画像に、今回の画像をプラスする。


今回プラスする分は新しくラベル4にした。CNNのコードは数カ所の数値を書き換えただけ。
前のサイトで書いてるけど、訓練画像とテスト画像の内訳は改めて書くと、こんな感じ。



訓練画像→ 合計 32340枚

Label 0 玄関 50, 廊下 50, リビング 150, 寝室 100, クローゼット 100 (増幅して6300枚)

Label 1 キッチン 300 (増幅して6000枚)

Label 2 トイレ 400, 風呂 150, 洗面化粧室 150 (増幅して7000枚)

Label 3 眺望 300枚 (増幅して6000枚)

Label 4 外観 3520枚 (増幅して7040枚)



テスト画像→ 合計 1063枚

Label 0 玄関 30, 廊下 30, リビング 30, 寝室 30, クローゼット 30 (150枚)

Label 1 キッチン 115(115枚)

Label 2 トイレ 80, 風呂 40, 洗面化粧室 40 (160枚)

Label 3 眺望 115 (115枚)

Label 4 外観 523枚(523枚)


新しくプラスした訓練画像も十分な枚数。DCGANから生成された画像でも、別に読み込ませた元画像に似てるわけではないので、元画像をテスト画像にしてみた。


仮にこれが上手くいけば500枚くらい画像を集めれば、訓練画像とテスト画像ができることになるので、ある意味画期的な手法ってことになる。



正解率

結果、正解率は48%

メッチャ低い。以前のCNNでは87.8%だったので、理由が知りたい、というわけでラベルごとの正解率をまとめてみた。

Label 0 80%

Label 1 83.9%

Label 2 91.5%

Label 3 94.5%

Label 4 3%



結果は見ての通り、ラベル0〜3は普通に高いのに、DCGANで作成した画像のラベル4が「3%」だった。



原因を考察してみる

外観画像は、ラベル3の眺望と結構似てるから

ラベル3の訓練画像に数枚ほど、外観とかなり似ている画像が含まれていたため、ラベル3に分類されたかもしれない。けど、数枚なのでその可能性は低い。
それよりもラベル3の眺望自体、他の建物も写ってるので、ラベル4の外観と似てる。そのため、ラベル4がラベル3に分類されてしまった可能性もある。

f:id:trafalbad:20171028214249p:plain


ちなみに純粋にラベル4の外観画像を、訓練画像、テスト画像ともにGoogle検索で収集したもので判別したときは、正解率は高かった。


DCGANで作成した画像は、元画像とは特徴抽出が違くて、まったく別物だから

生成された外観画像を画面上で見ると、人間には「外観」に充分見えるんだけど、CNNには全く別物に見えるらしい。多分、特徴量が本物の外観と全然違うのが一番の原因と考えられる。

スギャーンメモのサイトでも人間の顔と全く違う特徴抽出をしていたらしい。もう少し精巧に作れば、本物と同じように特徴抽出されるのかわからない。

とはいえ3%は低すぎるので、DCGANは本物の元画像とは似ても似つかないもののようだ




結論

やはり乱数から生成した画像は、人間には本物ぽくても、機械には別物で、本物同様の特徴抽出はされないことが原因っぽい。

外観の本物の画像を訓練画像に使った時は、ふつうに正解率が高かったことを考えると、やっぱりDCGANで作った画像は本物と違うらしく、データセットにはできないようだ。




今回はDCGANで生成した画像を使って、読み込ませた元画像を分類することができるか試したが、見事にコケた。CNN自体はかなり精度の高いものを使っているので、やっぱりDCGANの作成画像は本物も全く違うところに問題がある。
アイドル画像分類とかも、DCGAN生成画像を訓練画像にするなんてことは絶対できないだろうから、画像分類のデータセットはやっぱりキチンと集める必要がありそうだ。

VGGNetを参考にしたCNN(tensorflow)でマンション関連の画像を分類してみる

マンション関連の画像をCNNで分類する試みをしてみた。普通のcifar-10のモデルだと正解率が低かったが、VGGNet(Visual Geometry Group Networks)と呼ばれる高性能のCNNを実装しているサイト(すぎゃーんメモ)があったので、試しに実装してみたところ正解率87.8%を達成することができた。今回はそのログとして詳細を書いていこうと思う。


目次
1.画像の内訳
2.CNN
3.ラベル毎の正解率



1.画像の内訳

まず、訓練とテストに使った画像の枚数と、その内容の内訳は次の通りだ。


訓練画像→ 合計 25300枚
Label 0
玄関 50, 廊下 50, リビング 150, 寝室 100, クローゼット 100 (増幅して6300枚)

Label 1
キッチン 300 (増幅して6000枚)

Label 2
トイレ 400, 風呂 150, 洗面化粧室 150 (増幅して7000枚)

Label 3
眺望 300枚 (増幅して6000枚)



テスト画像→合計 540枚
Label 0
玄関 30, 廊下 30, リビング 30, 寝室 30, クローゼット 30 (150枚)

Label 1
キッチン 115(115枚)

Label 2
トイレ 80, 風呂 40, 洗面化粧室 40 (160枚)

Label 3
眺望 115 (115枚)

ラベル0〜3までの4種類で訓練画像は25300枚、テスト画像は540枚。
下にラベル毎の画像の一部を抜粋した。96pxで、左からラベル順になっている。

f:id:trafalbad:20170930083205p:plain

元画像は少ないものの、画像をうまく増幅させた(increacing_images.py)。画質に変化を加えるのは原則一回として、画質にあまり影響のない範囲で増幅させた。


元画像→ガンマ変換→コントラスト→.......→左右変換→角度変換

#左右変換
flip_img=[]
for i in seen5000:
    flip_img.append(cv2.flip(i, 1))

#角度変換
rad=np.pi/90 # circumference ratio
# distance to move to x-axis
move_x = 0
# distance to move to x-axis
move_y = 96 * -0.000000005
 
matrix = [[np.cos(rad),  -1 * np.sin(rad), move_x], [np.sin(rad),   np.cos(rad), move_y]]
 
affine_matrix3 = np.float32(matrix)
afn_90=[]
for i in gaikan:
    afn_90.append(cv2.warpAffine(i, affine_matrix3, size, flags=cv2.INTER_LINEAR))

”ガンマ変換”や”コントラスト”は元画像に一回しか適用できない。例えば”ガンマ変換”した画像にさらに”コントラスト”を適用すると画質がやばくなる。

しかし、”左右変換”と”角度変換”は”ガンマ変換やコントラスト”に適用しても画質は変換しないので、単純に全画像数を2倍にできる。最後にこの2つを持ってくることで効率よく画像を水増しできる。

”角度変換”は値を変えれば何回でも使えるので増幅にはおすすめだ。





2.CNN

元々はcifar-10のモデルで正解率を出したが、70%くらいだったので、もっといいのはないかと探していたところ、アイドル画像分類というサイト(すぎゃーんメモ)でVGGNetを参考にしたモデルが紹介されていた。かなりの精度だったので、今回はこれを適用してみた。


結果は87.8%というかなり精度の高い結果。cifar-10のシンプルなものよりも確実に上がっている。もっと層を厚くすれば正解率は上がりそうな気もするけど、精度としては十分なので、これを使った。


ただ唯一違うのはバッチノーマライゼーションを適用してる点だ。別に適用しなくても正解率はほとんど変わらないが、プーリング層だけのモデルと比較して2%ほど正解率が上昇した。

def cnn(x):
    BATCH_SIZE = 128
    def _variable_with_weight_decay(name, shape, stddev, wd):
        var = tf.get_variable(name, shape=shape, initializer=tf.truncated_normal_initializer(stddev=stddev))
        if wd is not None:
            weight_decay = tf.multiply(tf.nn.l2_loss(var), wd, name='weight_loss')
            tf.add_to_collection('losses', weight_decay)
        return var

    def _activation_summary(x):
        tensor_name = x.op.name
        tf.summary.histogram(tensor_name+'/activations', x)
        tf.summary.scalar(tensor_name + '/sparsity', tf.nn.zero_fraction(x))

    with tf.variable_scope('conv1') as scope:
        kernel = _variable_with_weight_decay('weights', shape=[3, 3, 3, 32], stddev=0.1, wd=0.0)
        conv = tf.nn.conv2d(x, kernel, [1, 1, 1, 1], padding='SAME')
        biases = tf.get_variable('biases', shape=[32], initializer=tf.constant_initializer(0.0))
        bias = tf.nn.bias_add(conv, biases)
        conv1 = tf.nn.relu(bias, name='conv1')
        _activation_summary(conv1)
    pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool1')
    norm1 = tf.nn.lrn(pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
    
    with tf.variable_scope('conv2') as scope:
        kernel = _variable_with_weight_decay('weights',shape=[3, 3, 32, 64],stddev=0.1,wd=0.0)
        conv = tf.nn.conv2d(norm1, kernel, [1, 1, 1, 1], padding='SAME')
        biases = tf.get_variable('biases', shape=[64], initializer=tf.constant_initializer(0.0))
        bias = tf.nn.bias_add(conv, biases)
        conv2 = tf.nn.relu(bias, name='conv2')
        _activation_summary(conv2)
    pool2 = tf.nn.max_pool(conv2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool2')
    norm2 = tf.nn.lrn(pool2, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
    
    with tf.variable_scope('conv3') as scope:
        kernel = _variable_with_weight_decay('weights',shape=[3, 3, 64, 128],stddev=0.1,wd=0.0)
        conv = tf.nn.conv2d(norm2, kernel, [1, 1, 1, 1], padding='SAME')
        biases = tf.get_variable('biases', shape=[128], initializer=tf.constant_initializer(0.0))
        bias = tf.nn.bias_add(conv, biases)
        conv3 = tf.nn.relu(bias, name='conv3')
        _activation_summary(conv3)
    pool3 = tf.nn.max_pool(conv3, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool3')
    norm3 = tf.nn.lrn(pool3, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
    
    with tf.variable_scope('conv4') as scope:
        kernel = _variable_with_weight_decay('weights',shape=[3, 3, 128, 256],stddev=5e-2,wd=0.0)
        conv = tf.nn.conv2d(norm3, kernel, [1, 1, 1, 1], padding='SAME')
        biases = tf.get_variable('biases', shape=[256], initializer=tf.constant_initializer(0.0))
        bias = tf.nn.bias_add(conv, biases)
        conv4 = tf.nn.relu(bias, name='conv4')
        _activation_summary(conv4)
    pool4 = tf.nn.max_pool(conv4, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool4')
    norm4 = tf.nn.lrn(pool4, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
    
    with tf.variable_scope('fc5') as scope:
        dim = 1
        for d in pool4.get_shape()[1:].as_list():
            dim *= d
        reshape = tf.reshape(pool4, [BATCH_SIZE, dim])
        weights = _variable_with_weight_decay('weights', shape=[dim, 1024],stddev=0.02, wd=0.005)
        biases = tf.get_variable('biases', shape=[1024], initializer=tf.constant_initializer(0.0))
        fc5 = tf.nn.relu(tf.nn.bias_add(tf.matmul(reshape, weights), biases), name='fc5')
        _activation_summary(fc5)

    with tf.variable_scope('fc6') as scope:
        weights = _variable_with_weight_decay('weights', shape=[1024, 256],stddev=0.02, wd=0.005)
        biases = tf.get_variable('biases', shape=[256], initializer=tf.constant_initializer(0.0))
        fc6 = tf.nn.relu(tf.nn.bias_add(tf.matmul(fc5, weights), biases), name='fc6')
        _activation_summary(fc6)

    with tf.variable_scope('fc7') as scope:
        weights = _variable_with_weight_decay('weights', [256, NUMCLASS], stddev=0.02, wd=0.0)
        biases = tf.get_variable('biases', shape=[NUMCLASS], initializer=tf.constant_initializer(0.0))
        fc7 = tf.nn.bias_add(tf.matmul(fc6, weights), biases, name='fc7')
        _activation_summary(fc7)

    return fc7   # shape=(BATCH_SIZE, NUMCLASS)

すぎゃーんメモではアイドル画像という単体の物体に適用していたが、今回はマンション関連の画像を対象にしたところがキー。どこが違うのかというと、マンション関連の画像は結構いろいろな関係ない物体が写っているので、

トイレ=トイレ
キッチン=キッチン

とキレイに分類できないところで、CNNも上手く分類できないのではないか心配だった。

しかし、ラベル設定を適切にして、ラベルを貼る人間がこれは「キッチンだな」とか「室内やな」みたいに確信を持って言えるほど混乱しない画像なら、CNNでも高い正解率は叩き出せるっぽい。

各ラベル毎の正解率は次にまとめた。





3.ラベル毎の正解率

各ラベル毎の正解率は以下の通り


Label 0 96.1%

Label 1 77.3%

Label 2 92.5%

Label 3 93.9%

トータルの正解率は87.8%だけど、ラベル毎の正解率を見てみるとやっぱり、キッチン画像がかなり正解率が低い。





→理由を考えてみる


室内 (Label 0)
→とりあえずベットとか天井とかあるので、室内とはわかる

キッチン (Label 1)
→基準が「コンロと水面台が写ってること」なので、それ以外にもいろいろ写ってるとわかりにくい

トイレ (Label 2)
→便器があればとりあえずわかる

眺望 (Label 3)
→景色の一部が画像の大半を占めているので、多分一番わかりやすい



キッチンは「コンロと水面台が写っている」を基準にした。しかし、他に別なものが写ってる確率が高いキッチンは、ラベル0の”室内”にカウントされてしまうっぽい。

下の画像はキッチンの画像だけど、人間でも「室内」といわれれば、そう見えなくもない感じなので、機械にも分類しにくいんだなと考えられる。


f:id:trafalbad:20170930141735p:plain



これが多分、正解率が下がった原因。ここは明確にキッチンとわかる画像を選べばいいんだけど、汎用性が高くないと意味がない。結局、慈悲は無粋だなというわけで、ちょっとわかりにくいのを配置してみたら結果的に正解率が微妙になった。


今回はマンション関連の画像を分類してみた。なんかいろいろとCNNの分類例はある。

けど、動物や顔だったりの単体の物体ばっかりで、鍋料理みたいにいろいろ入ってるマンション画像を分類する例はあまりないのではと思った。けどまあ、適切にラベル設定をして、ラベル付する人間でも迷わない範囲の画像ならCNNでも高い精度は出た。




*one-hot表現について
参考にしたすぎゃーんメモでは損失関数のところでone-hotを適用してたけど、cifar-10形式では特に必要ないらしい。ただしラベルは0から始めないといけないらしく、出力層(NUMCLASS)が4でもラベルは0〜3にしないといけない。これで一回ハマったので、注意。



本当はDCGANでデータセットを作ってから分類させようとしたんだけど、諸々の事情でCNNを先に試しました。DCGANは上手くいったらまた別記事で書く予定。

機械学習(ディープラーニング)画像認識・処理のための画像データ数値化&増やし方

今回は機械学習ディープラーニング)で画像データを収集し、それを増やす方法について書きます。

最終的にはDCGANで何かしら作成することを考えており、今回はDCGANのデータセットとして「より少ない手間で、よりたくさんのデータを作成する」をモットーに、画像データ収集法とそのデータを増やす方法(人工データ合成)をまとめておこうと思います。

目次
・画像データ収集方法
・画像のリサイズとラベル付け
・画像データを増やす方法

f:id:trafalbad:20170705152452j:plain



画像データ収集方法
画像のURLを集める
まず画像を集めるために、どっかしらのサイトからwebスクレイピングで画像のURLを収集します。一般的なサイトから画像のURLを取得する方法で、方法はいくつかある。
1.手作業で集める
2.サイトからスクレイピングする
3.Google Custom Search APIで画像を取得する

自分は手作業で集めました。スマホでポンポン保存して、AirDropでPCに送った。2のサイトからスクレイピングは限定的なので、3のGoogle Custom Search APIでのGoogle検索した画像をスクレイピングする方法がメジャーなようです。


ただ画像に著作権がある場合は、慎重になった方が良さそうです。

今回はスクレイピングした画像のURLを取得するケースを考えます。URLから画像を一括で取得するので、フォルダにURLの一覧を保存して、まとめておきます。



URLを画像に戻す
次はターミナルコマンドでフォルダのURLを画像に戻します。ターミナルから、

ls  
cd [保存場所]

でフォルダの場所に移行したら、下記のコマンドを入力します。

cat フォルダ名 | wget -I -

これでフォルダ内のURLが画像に変換され、downloadsに保存されます。一枚一枚保存されますので、新たなフォルダを作って保存し直します。


画像のリサイズとラベル付け


macで画像のリサイズ
次は画像の大きさがバラバラなので、縦、横を同じの正方形にして、好きなサイズにリサイズ。

今回は見やすさも考えて、128×128pxにしました。opencvpythonでリサイズもできますが、mac OSにフォルダ内のデータを一括してリサイズする機能が付属していますので、こちらを使います。

詳しくはこの記事を参照
これでフォルダ内の画像は一括してリサイズされます。



画像のラベル付けについて
画像にラベル付けする作業はとても面倒くさいので、それを簡単にする方法がいくつかあります。

方法1.ruby on railsのアプリを用いた方法
ruby on railsで画像を見ながらラベルをつけるアプリを作成しました。

trafalbad.hatenadiary.jp


画像を確認しながらラベル情報を入力するというのは普通は無理なんですが、それ用のrailsアプリを作った。

画像収集のレギュラーな方法としては、webスクレイピング→ラベル付けの順番でやるのが普通だと思います。


方法2.DCGANで同一カテゴリの画像を生成する方法
これはイレギュラーな方法です。今度試そうと思ってるんですが、DCGANでラベルのカテゴリ毎の画像を作成させる方法です。ラベルの種類が10個あったら、カテゴリ毎にDCGANに画像(つまり10種類の画像)を生成させ、データを増やそうと言うわけです。

まず少量のデータセットをカテゴリ別に作り、次にDCGANでカテゴリ別の画像を大量に作成させます。




こちらは実際にやってる人は見たことないんですが、DCGANの使い方としては非常に有能ではないかと思ってます。なぜなら、ラベル付けも必要ないし、データ収集も少量で済むからです。

本記事ではこの方法は触れませんが、別記事でDCGANの活用方法としてデータセットを増やすことについて触れたいと思ってます。



画像データを増やす方法
画像のデータが集まったら画像を増やしていきます。具体的にはopencvで左右反転させたり、色彩を淡くしたりする方法。画像をベクトルに変換することで、機械学習のデータとしては十分、学習データに値するものになります。


opencvで画像を数値化
まず、opencvのインストール(方法はこちらを参照)。フォルダ内の相対パスを取得して、画像を数値に変換します。

from PIL import Image
import os
import _pickle as cPickle
import os
import sys
import pickle
import numpy as np
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt

path1="フォルダパス"
images = os.listdir(path1)#画像の読み込み
img_batch=[]
for i in images:
    img_batch.append(cv2.imread(path1+'/'+i))#フォルダ内の画像を数値化

今回は変換した画像は300枚。各画像は(128, 128, 3)の形式です。画像を表示するときには、そのまんまmatplotlibで表示できます。



画像の増やす
変換した画像300枚を元手に画像を増やして行きます。今回はQiitaの画像水増しテクニックを使います。opencvで淡くしたり、することもできますが、画質が粗くなるケースがあるので、画像の質を保ちながら画像を増やすテクニックを使います。

方法はねずみ算式に増やしていきます。まず素画像300枚に反転をかけ、600枚に増やします。次に600枚にコントラスト調整をかけ、1200枚にします。この方法でねずみ算式に増やし、200枚の画像を、5000枚に増やすことができました。

本当はもっと増やせたんですが、128pxだと見易さの兼ね合いから平滑化など、の処理は省きました。
画像が見やすいものならQiitaの記事の通りにやって次のようにねずみ算式に300枚の画像を18000枚に増やして問題ないはずです。

コントラスト調整(300×2)
Salt&Pepperノイズ(600×2)
ガンマ変換(1200×2)
平滑化(2400×2)
ガウス分布に基づくノイズ(4800×2)
反転(9600×2)

最後に「反転」をかけるのがコツです。こうすることで、より多くの画像の鮮明度を保持することが可能になります。
ちなみに「角度変換」をかけることで「反転」と同じ効果が得られます。「角度変換」は値を変えると何回も使えるので2倍に増やすには本当に便利。

rad=np.pi/220 # 角度変換
# distance to move to x-axis
move_x = 0
# distance to move to x-axis
move_y = 96 * -0.00000000000000006
 
matrix = [[np.cos(rad),  -1 * np.sin(rad), move_x], [np.sin(rad),   np.cos(rad), move_y]]
 
affine_matrix3 = np.float32(matrix)
px_size=(96,96)
afn=[]
for i in seen10000:
    afn.append(cv2.warpAffine(i, affine_matrix3, px_size, flags=cv2.INTER_LINEAR))


matplotlibで64枚を可視化してみる

tensorflowでも複数の画像をまとめて表示する方法があります。今回はそれを真似てnumpyとmatplotlibを使って可視化。


今回は元画像64枚一気に表示します。



f:id:trafalbad:20170930141735p:plain


今のところはどんな画像かを確認するためのもの。なので、そんなに凝らなくていいと思ったので64枚一気に表示させてみました。

iti=t_image[160:230]
col=8
rows = []
for i in range(8):
    rows.append(np.hstack(iti[col * i + 0:col * i + col]))
plt.imshow(np.vstack(rows))
plt.show() #淡くしたの64枚可視化



今回は画像のデータを収集&増やす方法を書きました。まあopencvを使えば簡単なのですが、案外まとめてあるサイトがなかったのでまとめました。


この画像を元にDCGANで何かしてみようと思ってます。特にデータセットを増やすことができたら、かなり有用性があるのではと思いますが。そこら辺も含めてDCGANについてはまた別記事で書くつもり。

無理して結婚しなくてもいい生き方-独身でも自由に生きる人生について考えてみる

最近は結婚する人たちを周りでかなり見かけるのに伴い、自分もしなければならないという強迫観念に襲われる。しかし、実際のところ最近では「結婚しなくてもいい」という考えの人も多いので、自分も縛られたくないため、なるべく無理して結婚はしたくない。

そこで結婚しなくても人生を楽しみ、自由に生きていくための方法について、個人的にとても参考になることをまとめていきたい。

目次
・「したくない結婚」はしない方がいい
・結婚しなくても自由な人生を送るために

f:id:trafalbad:20170618011003j:plain


「したくない結婚」はしない方がいい

日本にはまだ昭和の考えが根付いてて、「結婚しないとヤバイよ」という強迫観念がどよめいている。しかし最近では自由な人生を選択するために「結婚」はマストではなくなった

自分は「したくない結婚」はしない方がいいという考えだ。ニュートラルな意見を述べると理由は2つある。



独身はとにかく自由
まず理由の1つは独身生活の利点で、というのも、「行動や生き方が自由」だからだ。明治安田生活福祉研究所の調査によると、「あえて結婚しない人」の割合は年々増えている。

35歳から54歳の未婚者の約半数が「あえて結婚していない」として、結婚を望んでいないことが分かりました。

35歳から54歳の男女1万による調査によると未婚者の49%が「あえて結婚していない」と答え、「結婚したいができていない」の51%とほぼ同数。「あえて結婚しない」理由としては「元々、結婚を望んでいない」という独身主義が最も多く、「独身は精神的・時間的に自由がきく」が続いています。また、男女とも年齢が高くなるほど「今さら、結婚するような年齢ではない」との回答が多くなっています。
引用-「ANN NEWS」


イヤイヤ結婚して束縛されるなら、いつまでも自由で好奇心を持ち続け、楽しい人生を送っていたいのだ。こう考える人も確実に増えている


昔から一人の時間を大切にする方だったし、人間関係も量より質を重視してきた。むしろ1人が好きな人には、無理して結婚することは、QOLを下げることになる。



結婚という強迫観念が古い
2つめの理由は結婚しなければいけないというのが一種の脅迫観念で、「結婚するのがステータス」な考え方がすでに”クソ”だと思っているため。またそういう人たちが多数いるのも事実だ。

最近では結婚系の記事がを目にすることが多いが、中には「好きでもない人と結婚する人たち」もいるのだ。

現代でも、結婚の理由は親のため、世俗のため、孤独回避のため、子供を持つことに幸せにを感じるため、など人それぞれだが、強迫観念に囚われて結婚するのは、クソ以外の何者でもない

結婚が全てではないし、結婚のあるべき形とは”お互いが望んでするもの”がベストと考えるからだ。

年頃になると結婚について嫌でも考えてしまうが、むしろ結婚は「したくてするもの」で、結婚しなくてもいい選択肢を用意しておくことも絶対に必要だろう



結婚しなくても自由な人生を送るために
結婚という強迫観念は簡単に拭えるものではない。しかし、自由に生きている人たちも絶対数いることを確認した上で、その強迫観念を拭える一助になれたらと思う。


結婚しなくても人生を楽しむ人たち

Twitter

つい最近、Twitterでさわぐちけいすけさんのツイートが話題になっていた。フリーで絵の仕事を始めてから、いろんな人生観に触れている様子を漫画にしている。


このツイートを見てみると

・仕事が楽しくて定年まで結婚しなかった人

・常に人生を楽しんでて結婚は考えない人

・今を大事にして結婚にエネルギーをさくのを避ける人

など、いろんな生き方をしている人たちがいることがわかる。

f:id:trafalbad:20170618011334j:plain



発言小町



同じように発言小町でもこんなコメントがあった。


必死に友達に年賀状や近況報告メール等出して「縁」を繋ぎとめて置く事に精を出しました。彼氏も作ろうとしました。でも好きな人がいる訳でもないのに漠然と彼氏って思っても、自分の気が乗らずダメでした。
ある時「やっぱり自分が自立した人間にならないと始まらない」と思いました。トピ主さんの行きついた所と似てます。

必要とされたいから人と付き合うのではなく、自分で自分の人生を楽しんでいれば自然とその喜びを誰かと共有したいと思うようになります。そうすると、繋ぎ止めの目的ではなく心から友達と遊べるようになりました。
自立さえできれば、結婚しない人生どころかどんな人生が来ても対応できるようになると思うんです。
一部略-引用「結婚しない人生を送る覚悟が欲しい : 恋愛・結婚・離婚 : 発言小町 : YOMIURI ONLINE(読売新聞)



結婚しなくても自由に生きるためには、縁を繋ぎとめようとしたり、無理して人間関係を維持しようとはしないこと。

自分も心底、人生を楽しみ、それを一緒に楽しめる人と共有したり、楽しみあったりすことを目指す生き方。それさえできれば結婚しなくても、十分楽しい人生を送ることができる。

互いの人生を一緒に楽しめるパートナーが見つかれば、結婚したり、同棲したり共に人生を送ればいいだろう。むしろ結婚というステレオタイプは崩壊しているのがわかると思う。

もっと多面的な生き方を、考え方を持った方が人は幸せになれる。

ラフな考え方を持ち、より身軽になるために、こういう人たちが必ずいることを忘れないでおきたい

f:id:trafalbad:20170618011145j:plain



アルバイト先の年配女性に聞いた体験談まとめ


ここで結婚に関して、アルバイトをしていたとき年配の女性の方から、とても参考になる話を聞いたので、簡単にまとめておこうと思う。

「結婚で理想なのはお互いにしばりあわない関係。大概のことなら何をしても互いに常に自由で、かつずっと一緒にいられる関係が一番」

つまり、結婚するパートナーでも、結婚するからといって相手の人生を束縛しない。そしてお互い一緒にいて苦にならない人生関係が理想だということらしい。

友達関係でも依存しすぎのかまってちゃんは嫌われる傾向があるが、結婚という形態でもそれは同じなのだろう。

一個人の人生を束縛せず、かつ一緒にいて楽しい人がいれば、その人は絶対のパートナーになるのではないだろうか。
あらゆる人間関係に当てはまる理想的な関係だと思う。年配の女性に聞いた体験談だが、かなり参考になったので、まとめておいた。




年頃になると結婚はどうしても意識してしまう。しかし「結婚したくないならしない人生も十分にありなんだ」ということを悟ってもらえたら幸いだ。自分へのメッセージとしてもこの記事をまとめておいた。