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

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

xgboostの回帰モデルで精度検証から重要な特徴量選択までやってみた全行程まとめ(機械学習)

今回はkaggleでよくある特徴量エンジニアリングのテクを使って、精度向上から重要な特徴選択までをやった。普通は精度高ければ終わり的な感じだけど、今回は精度検証からさらに掘り下げて、特徴量の選択までやったので、その過程を書いてく。

目次
・プロジェクト紹介
・デーセット
・特徴量作成
・モデル構築
・正解率
・特徴量の探索(分析)
・最後に(反省点)

コードはこちら




プロジェクト紹介


一回しか購入しないユーザー(u1)と2回以上購入しているユーザー(u2)を分ける重要な特徴量を見つけるプロジェクト。目的は一回しか買わないユーザーに有効な施策をうつこと。

よくある特徴量エンジニアリングで、回帰モデルを使って精度を競うkaggleとかのコンペと似ている。けど、今回は精度検証後に重要な特徴量選択までしたので、特徴量選択の分析過程も含まれてる。全体の工程としては、特徴量作成が7、8割を占めた感じ。

特徴量エンジニアリングが、精度向上に重要な過程だと再認識。





データセット


データセットはデータベースに保存してあるテーブルのレコード(特徴量)から選択して作成。kaggleみたいにあらかじめ綺麗なのが用意されてないし、データベースとbigqueryに別々に保存してある。そんな中、無数にある特徴量から適切なのをSQLで取り出して、ベストな特徴量を作成。

最終的な特徴量は、2回目の検証結果から決めた。アルゴリズムでの検証は全体で3回。

まず1回目は商品に結びつきそうな特徴量を選んで検証。1回目はtouroku_dateという特徴量が一番重要らしく、次の特徴量を選ぶ指針になった。

2回目は施策から「u1が1回で購入をやめてしまう」ことに関する仮説を立てて、この仮説に直結する特徴を選んで使うことにした。
仮説の設定はAmazonとか、リピート率が鬼のように高いサイトレビューとかを参考にした。


一回で購入をやめてしまう or 継続して購入する理由の仮説

=> 評価の悪いユーザーから購入してる
=> レコメンド関係の施策で欲しい商品を購入してる
=> 欲しい商品が見つからない(時間をかけて探していない)



3回目は特徴量を2個追加して、若干の修正後に再検証。






***仮説を立てることで作業を効率化
無数にある特徴量の中から、適切なものを選択する過程で、施策に応じて仮説を立てる作業はかなりの効率化につながった。はじめに仮説を立てるのは、データサイエンティスト的な手法らしい。

さらに、選んだ特徴量から、u1とu2間の違いをあらかじめ調べる作業をする事で、さらに効率化。違いを見るのには「標準偏差・平均・中央値」とかの分析手法を使った。

特徴量は何を選べばいいかわからない状況下で、

・仮説の設定

・違いを見る作業

この二つをすることで、かなり効率化できた。

特徴量に必要な特徴量を選択するまでの、全行程はこんな感じ

1、まず分類に使えそうな特徴量を作成・検証

2、試作にあった仮説を立てる(重要)

3、仮説に直結する特徴量を選んで、標準偏差とかで違いをみる(重要)

4、特徴量を決めて、作成

2、3の作業が一番精度向上につながった。

最終的なデータセットは、
特徴量10こ
u1は250853件、u2は1169898件のデータを使った。




特徴量作成


特徴量の作成過程は上で書いた通りなので、ここではデータベースのレコードをSQLで取り出し、それを使いやすい形に変えて特徴量を作成する特徴量エンジニアリングのテクニックについて触れたい。

特徴量エンジニアリングでは主に質的変数(赤、青、白とかみたいな数字じゃない形)をダミー変数に、量的変数(体重とか身長みたいな数値)を使いやすく変形させるテクがある。

特にダミー変数は離散化とか、いろいろあるので、ここら辺の資料を参考にした。

機械学習レシピ#3

データの前処理だけで競馬は強くなる

特徴量の形を使いやすい形に変えるのも、めっちゃ大事。
今回は可視化した結果の分布が、「0が多く、0以上が少ない」場合、SQLでこんな感じに取り出すのが有効だった。

SUM(case when レコード= 値 then 1 else 0 end) 


逆に分布がバラバラな特徴量は、AVG() で平均をとるか、そのまま使うのが有効だった。

特徴量は検証前に、標準化しないと分類精度がすごい下がるので、データ作成後は必ず標準化した。






モデル構築


モデルは、kaggleで有名なランダムファレストの改良版のxgboostを使った。
特にGBDTの改良手法Dropouts meet Multiple Addtive Regression Trees(DART)とパラメーターチューニングのhyperoptの組み合わせが、xgboostとドンピシャで、かなりいい分析精度になった。

xgboostのパラメータは山ほどあるので、チューニングはベストプラクティスを載せてるサイトがを参考にした。

Parameter_Tuning_XGBoost_with_Example

パラメータチューニングはhyperoptとgridseachを使い分けて、手早くチューニング。

精度検証で、交差検証はもはや当たり前で、さらに複数のアルゴリズムでの検証や、複数の精度指標での試行錯誤も王道らしい。

def objective(params):

    skf = cross_validation.StratifiedKFold(
        train_y, # Samples to split in K folds
        n_folds=5, # Number of folds. Must be at least 2.
        shuffle=True, # Whether to shuffle each stratification of the data before splitting into batches.
        random_state=30 # pseudo-random number generator state used for shuffling
    )

    boost_rounds = []
    score = []

    for train, test in skf:
        _train_x, _test_x, _train_y, _test_y = \
            train_x[train], train_x[test], train_y[train], train_y[test]

        train_xd = xgb.DMatrix(_train_x, label=_train_y)
        test_xd = xgb.DMatrix(_test_x, label=_test_y)
        watchlist = [(train_xd, 'train'),(test_xd, 'eval')]

        model = xgb.train(
            params,
            train_xd,
            num_boost_round=100,
            evals=watchlist,
            early_stopping_rounds=30
        )

        boost_rounds.append(model.best_iteration)
        score.append(model.best_score)

    print('average of best iteration:', np.average(boost_rounds))
    return {'loss': np.average(score), 'status': STATUS_OK}

def optimize(trials):
    space = {'booster':'dart',
         'learning_rate':0.1,
         'n_estimators':1000,
         'sample_type':'uniform',
         'normalize_type': 'tree',
         'objective':'binary:logistic',
         'min_child_weight':1,
         'max_depth':9,
         'gamma':0.0,
         'subsample':0.6,
         'colsample_bytree':0.9,
         'reg_alpha':1e-05,
         'nthread':4,
         'scale_pos_weight':1,
         'seed':27,}
    
    # minimize the objective over the space
    best_params = fmin(
        fn=objective,
        space=space,
        algo=tpe.suggest,
        trials=trials,
        max_evals=10
    )

    return best_params

# parameter tuning
trials = Trials()
best_params = optimize(trials)
print(best_params)

# 損失関数(loss)の計算
print(objective(best_params))






正解率


正解率は


AUCで89.33%



MCCで0.548(-1~1の範囲をとり、1で100%の精度)



特徴量の重要度


評価指標はAUCがよく使われるけど、不均衡データとかより正確な精度判定にはMCCの方がいいっぽい。

from sklearn.metrics import matthews_corrcoef
thresholds = np.linspace(0.01, 0.99, 50)
mcc = np.array([matthews_corrcoef(test_y, pred_y>thr) for thr in thresholds])
plt.plot(thresholds, mcc)
best_threshold = thresholds[mcc.argmax()]
print(mcc.max())

この他にも混合行列とかF値を使ってもいいけど、今回はMCCがF値と同じくらい精密なので、MCCで代用。




特徴量の探索(分析)



特徴量の重要度、そのツリー、xgboostの結果から、u1とu2に有効な特徴量選択。検証からさらに特徴量を探すまで深掘りするケースはサイトでは見つからなかったので、このフェーズが一番大変だった。
とりあえず、一般的な統計手法とか、マーケット分析事例で使われてるっぽい分析手法を漁った。

あとは知識、ひらめき、そしてひたすら根気の作業。
結果、ヒストグラムクラスタリング、次元削減、重回帰分析とかが使えるっぽくて、一番合理的な「重回帰分析」を使った。

重回帰分析は、ある一つの特徴量と、他の複数の特徴量の相関関係を計算してくれる

結果的に、

u1=>海外商品系の特徴量

u2=>満足度が高い特徴量

との相関が高く、これらが重要な特徴量と判断。

結論とその理由とかのロジック的な部分は、他の特徴量との相関関係の数値、仮説の消去法で導いた感じ。ちゃんと根拠つきで




最後に(反省点)



kaggleとかの特徴量エンジニアリングを使った分析は、あらかじめ綺麗な特徴量が用意されていて、分析精度が良ければ終わり、みたいなケースが多い。
けど今回はさらに掘り下げて、重要な特徴量の選択までやった。前例がないとほぼ手探りなので、かなり大変だった。

とりあえず、反省点として

・試行錯誤より頭を使って、作業量を減らす(think more, do less)

・行き詰まったり、停滞したら、一回止まって問題の分解とか本質の問題探しをする。絶対にただタスクをこなすだけのループにはまらないこと
(今回はマッキンゼーの問題解決法の書籍が本質の問題探しにかなり使えた
イシューからはじめよ―知的生産の「シンプルな本質」
世界一やさしい問題解決の授業―自分で考え、行動する力が身につく


・チームで動く以上、進歩確認は随時やる


・データ量が多ければ、少ないデータ量(1万件くらい)で試す


・やることの意思疎通にすれ違いがないようにして、やり直しは極力やらない


・段取り8割


・わからないことは、詳しい人に積極的に、遠慮なく聞くこと

あえてxgboostのDARTみたいなハイリスク・ハイリターンのスキルを使うことで、かなりのスキルが身についたなと実感した。




kaggleのテクニック系の参考資料
top2%の私が教えるKaggleの極意

Kaggleで使われた特徴量エンジニアリングとアルゴリズムまとめ

Djangoでアップロードした画像をCNNで予測し、結果を返すアプリを作ってみた(画像認識、機械学習)

kerasで作った画像分類器に画像を読み込ませ、予測したラベルのidを返すアプリ作った。以前、rubyで作ったことがあるけど、今回はpython専用のフレームワークDjangoを使って作成。

画像分類器にはCNNを使ったので、GPUとか学習のところは割愛して、アプリ作成過程についてだけ書いてみる。

目次
1.アプリについて
2.メインのファイル



1.アプリについて


一通りの動作
デフォルトのホーム画面はこんな感じでシンプル

写真をアップロードして、クリックすると予測した確率が高いトップ3のラベルのidが表示される仕組み


アプリ名と構成ファイル
project名はimage_pred

アプリ名はmyapp

メインの構成ファイルは
・setting.py
・forms.py
・views.py
・index.html
・main.py
・urls.py

いろんなファイルを保存するディレクトリは、必要に応じて作成した。




MVCフレームワークについて

DjangoでのMVCフレームワーク

・Mはmodels.pyでデータベースの操作

・Vはviews.pyで画面の表示を操作

・Cはurls.pyでアクセス関係の操作

今回はデータベースにデータを保存しなくていいので、models.pyは使わない。使うときはマイグレーションが必要で、使えるデータベースは任意に指定可能

便利なパッケージでdjango-cleanupがあった。データベースを使うならpipでインストールして、setting.pyのINSTALLED_APPSに入れておきたい





2.メインのファイル


まずパッケージは
・Pillow
・keras
・tensorflow
opencv

とかをpipでインストール





setting.py
myapp作成後に、INSTALLED_APPSにmyappを追加。

画像をアップロードするので以下のディレクトリを設定
・MEDIA_ROOT
=>サーバから見たメディアルートの絶対パス

・MEDIA_URL
=>メディアファイル公開時のURLのプレフィクス。 メディアファイルのURLは「http://アプリのドメイン+MEDIA_URL+メディアファイル名」

# 一部掲載
import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SECRET_KEY = '8bdf)xh2b4h!8#g$i0j_9pymjld*ov19!rpfgj2qsi6j)-$t9d'

DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp' # 追加
]

STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'






forms.py
ここは画像をアップロードする専用のフォームを作成するファイル
画像専用フォーム「forms.ImageField()」を使用

from django import forms

class PhotoForm(forms.Form):
    
    image = forms.ImageField()






index.html

ここはメインのホーム画面を表示するhtml。主にしてる処理は
・main.pyで予測したラベルのidをhtmlの変数に埋め込み、レンダリング
・フォームの設定
・静的ファイル(CSS)の読み込み
など。htmlにpythonの変数を直接、埋め込めるのがDjangoの強み

{% load static %}
<!doctype html>
<html lang="ja">
<head>
 <meta charset="utf-8">
 <title>img_prediction</title>
 <link rel="stylesheet" type="text/css"
      href="{% static 'myapp/css/style.css' %}" />
</head>
<body>
<p>{{pred}}</p>
<table>
<form action="{% url 'index' %}" method="POST" enctype="multipart/form-data">
   {% csrf_token %}
   {{ form }}
   <tr><td></td><td><input type="submit" value="click" /></td></tr>
</form>
</table>
</body>
</html>


静的ファイルは{% load フォルダ名 %}を記述してCSSを読み込ませた。 staticファルダ内にstyle.cssが保存してある。javascriptとかも同じように読み込める

変数は{{pred}}の部分。

フォームはformタグ内に記述。画像の場合はenctype="multipart/form-data"を指定しなきゃだめ







main.py
コードはkerasで作成した学習済みの画像分類器(CNN)と予測結果を返す処理。学習済みの重み、id用のcsvファイルは専用フォルダを別途作成して、保存してる。

# pred関数のみ
def pred(img_path):
    sess = tf.Session()
    K.set_session(sess)
    cnt=pd.read_csv('/Users/d/image_pred/myapp/weight_dir/cnt.csv')
    cnt=cnt.drop('Unnamed: 0', axis=1)
    cnt=cnt.drop('cnt', axis=1)
    
    
    dic = {}
    for i, v in cnt.iterrows():
        dic.setdefault(v['index'], []).append([v['brand_id'], v['model_id'], v['cate_id']])
    
    x=np.asarray(Image.open(img_path))
    x = cv2.resize(x, (100, 100))
    x = np.expand_dims(x, axis=0)
    image = preprocess_input(x)

    test_model = InceptionResNetV2(include_top=True)
    test_model.load_weights('/Users/d/image_pred/myapp/weight_dir/incep_model.h5')
    test_model.compile(optimizer=SGD(lr=0.01, momentum=0.9, decay=0.001, nesterov=True),
                    loss='categorical_crossentropy', 
                    metrics=['accuracy'])

    y_pred = test_model.predict(image)
    top_k=sess.run(tf.nn.top_k(y_pred,k=3,sorted=True))
    idxs=list(np.reshape(top_k[1],(3,)))
    id=[]
    for idx, v in dic.items():
        if idx in idxs:
            id.append(['brand_id:{} model_id:{}, cate_id:{}'.format(v[0][0], v[0][1], v[0][2])])
    return id





views.py
ここは、index.htmlへのレンダリングなど、表示関連の処理を書くとこ。

主に、get時の処理とpost時の処理を関数に分けて書いてある。get時の処理はアクセス時のデフォルトの画面表示。

post時の処理はアップロードして画像を受け取って読み込み、予測したラベルのidを返す処理を書いてる。
フォームからアップロードされた画像を読み込み予測ラベルを返す処理はmain.pyのpred関数をimportで呼び出す。そして、変数を代入して、その結果をhtmlにレンダリング。画像じゃなきゃエラーを返す仕組み

from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.views.generic import TemplateView
from .forms import PhotoForm
from myapp.main import pred

class MyappView(TemplateView):
   def __init__(self):
       self.params={'pred': 'idx',
                    'form': PhotoForm()}
   def get(self, req):
       return render(req, 'myapp/index.html', self.params)

   def post(self, req):
       form = PhotoForm(req.POST, req.FILES)
       if not form.is_valid():
           raise ValueError('invalid form')

       image = form.cleaned_data['image']
       self.params['pred'] = pred(image)
       return render(req, 'myapp/index.html', self.params)





urls.py

Djangoではプロジェクトの下にいくつもアプリを作れる。Djangoでは「1アプリ=1 url」が基本。つまりurls.pyはアプリを作るたびに、プロジェクトの階層以外にも。アプリ内に必ず一つurls.pyを配置する仕組み




・プロジェクトの階層のurls.py
プロジェクトの階層では全てのアプリのurls.pyを管理するpathを指定する。「アプリのことは各アプリ内のurls.pyに聞け」って意味のinclude()を使う

urlpatterns = [
   path('admin/', admin.site.urls),
   path('myapp/', include('myapp.urls')),]


・各アプリ内のurls.py
各アプリ内ではurlspatternにurlを指定する。引数は3つあって、1つめはhttp://~/myapp/の後に続くアドレス、2つめはアクセスするファイル、3つめは指定したurlの名前


from django.conf.urls import url
from .views import MyappView
urlpatterns = [
              url(r'', MyappView.as_view(), name='index'),
              ]


画像をアップロードするたびにファルダにurlと画像が保存されるようにするには以下を追加。

if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)




動作確認

画像をアップロードしてクリックを押す

すると、予測ラベルのidが表示される。

idを返す超単純なアプリを作成した。Djangoの勉強とアウトプットには、やっぱり基礎を抑えて自分でアプリとか作るのが一番っぽい


参考記事

Django - 画像ファイルのアップロード処理

Django-ファイルアップロード機能の使い方 (基本設定編)

Djangoで、けものフレンズキャラの顔を認識させる(Deep Learning)

LSTMを使って異常検知手法で急上昇ワードをやってみた(機械学習-変化点検知)

急上昇ワード(バースト検知)とえば、googleyahoo!でも似たようのがある。今回はあれほど高性能じゃないけど、急上昇ワードと同じ仕組みのものを異常検知手法でやってみた。

目次
・訓練
閾値の設定
・テスト
・実際に急上昇ワードをやってみる

今回はBigQuery(BQ)から抜き出した、一定期間内の検索ワードの急上昇を検知してみる。みんな大好きニューラルネットワークのLSTMで訓練し、バースト検知に利用した。訓練から、実際にBQから取り出した検索ワードの急上昇検知実行までの流れを一通り書いて行く。

実際の全体コードはgithubにあげてあります。




訓練


まず訓練データ、「mizugi」と「bts」というワードを2つ、8ヶ月分ほど抽出。btsは2桁(10台)の検索数が多く、mizugiは検索数が多く、3桁(100〜1000)のワードだ。
まずLSTMでbtsを8ヶ月分くらい、急上昇部分があっても構わず学習させた。


btsとmizugiの急上昇部分は特異変換スペクトルで検出した。結果がこれ

bts

mizugi

アルゴリズムはLSTMを使った。QRNNとかいう発展版も試したが、LSTMの方がkerasで簡単に使えるし、十分なので途中で断念。

データをLSTMで使えるようにする正規化とかの前処理と、モデル作成はこんな感じ

def get_data(data, time_steps):
    docX, docY = [], []
    for i in range(len(data)-time_steps):
        docX.append(data[i:i+time_steps])
        docY.append(data[i+time_steps])
    alsX = np.array(docX)
    alsY = np.array(docY)
    return alsX, alsY

def transform_data(data, inverse_option, scaler):
    data_shape = data.shape
    if inverse_option is True:
        data = scaler.inverse_transform(data)
    else:
        data = scaler.fit_transform(data)
    data = data.reshape(data_shape)
    return data, scaler

def prepare_data(original_data, time_steps):
    copy_data = original_data.copy()
    scaler = MinMaxScaler(feature_range=(0, 1), copy=False)
    data, scaler = transform_data(data=copy_data, 
                              inverse_option=False, scaler=scaler)
    
    x,y = get_data(data, time_steps=time_steps)
    return x, y, scaler

time_steps = 12

x, y, scaler = prepare_data(X_train, time_steps)

input_dim=x.shape[-1]
timesteps=x.shape[1]

model = Sequential()
model.add(LSTM(300, input_shape=(timesteps, input_dim),
         stateful=False,return_sequences=True))
model.add(Flatten())
model.add(Dense(1, kernel_initializer='lecun_uniform'))
model.add(Activation("linear"))
# model.load_weights('/Users/d/model.ep200.h5')
model.compile(loss="mean_squared_error", optimizer="adam",)

以下が訓練後、btsの学習期間を予測した図。赤がリアルの検索数値で青が予測値だ。btsは2桁の値なのか知らないけど、損失関数はあまり減少しなかった。学習結果としてはいまいちだったけど、それなりによく予測できてたかな。

btsの予測


閾値の設定


ここからbtsとmizugiから以下のように検証・テスト1・テスト2の3つにデータを分けた

・検証データ→btsの急上昇のない部分(異常なしデータ)

・テストデータ1→btsの急上昇のある部分(異常ありデータ)

・テストデータ2→mizugiの急上昇のある部分(異常ありデータ)


バースト検知は異常検知の中で「変化点検出」に当たる。

それには少し変わった閾値設定をする必要がある。以下の流れで閾値を設定した。

①検証データはオリジナルの閾値の設定に使用

②検知したいワードの平均値をオリジナルの閾値にかけて、その検知したいワードに最適な閾値を再設定する


変化点検知の閾値設定には、回帰(予測)モデルと、mseの組み合わせから求めるのが、結構メジャーらしい(参考記事)。




①検証データはオリジナルの閾値の設定に使用

今回の閾値の設定には、検証データを使って最初の(オリジナルの)閾値を求めた。コードは以下の通り。

def calculate_mse(value, predict_value, variance=1.0):
    value = value[:, 0]
    predict_value = predict_value[:, 0]
    mse_value = [(v - p_v)**2 for v, p_v in zip(value, predict_value)]
    return np.array(mse_value)


mse_value_valid = calculate_mse(x_scale_valid, predict_valid)
threshold = np.max(mse_value_valid)
# threshold:249.16269761799867

検証データ(異常なしデータ)の全期間から、MSEを求めて、その最大値を閾値とした(つまり、検証データの異常値の最大値)。




②検知したいワードの平均値をオリジナルの閾値にかけて、その検知したいワードに最適な閾値を再設定する


ここで問題なのは。btsは2桁の値なので閾値はかなり低い。これを水着のような3桁、4桁以上の検索数のワードに適用すると閾値が小さすぎて、全部の異常値を検出してしまう。


そこで検知するワードに対して最適な閾値を再設定してやる必要がある。以下のやり方で設定した。


1.検証データから求めたMSEの最大値をオリジナルの閾値とする

2.検知したいワードの全期間の検索数の平均値割る2の値を四捨五入して整数にする

3.それをオリジナルの閾値にかけて、検知したいワードの閾値(high_threshold)として再設定

わかりにくいので、コードで表すとこんな感じ

mse_value_normal = calculate_mse(x_scale_train, predict_train)
N=int(np.mean(x_scale_train)/2)
high_threshold = threshold*N 

なんで2で割ったのかは、いろいろ試して一番検出に適した値になるからなので、別に整数(int)じゃなくて、小数(float)のままでもよかった。





テスト


再設定した閾値で、テストデータ1、2のバースト(異常)を上手く検知できてるか試す。

上からテストデータ1(bts)、テストデータ2(mizugi)の時系列データと、再設定した閾値をプロットした

bts

mizugi

元の閾値よりも高い閾値で、程よく急上昇部分が検知されてる。一日、1週間、一月の期間でも試したが、上手く検出できてた。





実際に急上昇ワードをやってみる


いよいよ、バースト検知を試してみる。今回はjupyter上から直接、検索ワードをBigQueryから抽出して、検出してみた。


急上昇検知のメイン部分はこんな感じ

csvs=[]
original_threshold = 270.2200 
train_data_mean=4.964
num_words=len(words)
for i in range(num_words):
    cnt=pd.DataFrame(list(cnt_listed[i][0])).dropna()
    hour=pd.DataFrame(list(hour_listed[i][0])).dropna()
    hours=np.array(hour[window:])
    wo=cnt_listed[i][1] # each word
    
    x_predict, y_ ,scaler = prepare_data(cnt, time_steps)
    predicted, x_scale, mse_value = predict_model_show_graph(hour[window:], x_predict, y_, scaler, model, time_steps)
    mse_value = calculate_mse(x_scale, predicted)
    
    N=int(np.mean(x_scale)/2)
    high_threshold = original_threshold*N  # 閾値
    if high_threshold<original_threshold:
        #print('high_threshold: {}'.format(original_threshold))
        #show_graph_threshold(hour[window:], mse_value, original_threshold, 'Anomaly Score test', "r")
        # 急上昇ワードの時間を表示
        for mse, hour in zip(mse_value, hours):
            if mse >=original_threshold:
                csvs.append([hour, wo])
    else:
        #print('high_threshold: {}'.format(high_threshold))
        #show_graph_threshold(hour[window:], mse_value, high_threshold, 'Anomaly Score test', "r")
        # 急上昇ワードの時間を表示
        for mse, hour in zip(mse_value, hours):
            if mse >=high_threshold:
                csvs.append([hour, wo])

その前の前処理では、取り出したワードを時系列データに変換したり、LSTM用に正規化したりした。

今回は3月3日の分だけ、検索ワードを取り出して、検知。図をplotとするといい具合に検出できてるっぽい。

最終的には、ワードと時間を抽出する形にした。


閾値の設定は前に書いた動的時間伸縮法(DTW)でもできるけど、計算量がバカにならない。なので、MSEとかのローコストな計算式を臨機応変に使い分けるのが最適だと思う




今回はLSTMを用いた、変化点検出手法で急上昇ワードのバースト検知をやってみた。
昔はchange finderとかsmartfilterとか、ゴツい検出アルゴリズムがあったけど、ニューラルネットワークの登場で異常検知もかなりやりやすく、精度も高くなった。

異常行動検知もLSTMを使ってできる。機械学習シリーズにある密度比推定とか非構造学習みたなガチもんの専門的な内容には、機会があったら触れてみたい。

列名とかデータ加工に使うpandasの便利な機能まとめ (python・機械学習)

今回はデータ加工に使えるpandasの機能を紹介する。kaggleを含め、機械学習のデータ加工はpandasでの加工が多い。

理由は単純にpandasはデータ加工において、扱いやすいから。今回はxgboostの特徴量を加工する機会があった。そのときに使ったり、調査したkaggleで人気なpandasのメソッドの中で使えそうなやつをまとめた。


機能1〜5まではここではirisデータセットで試した。

iris = datasets.load_iris()
df_feature_iris = pd.DataFrame(iris['data'],columns=['sepal_length','sepal_width','petal_length','petal_width'])
df_species_iris = pd.DataFrame(iris['target'],columns=['species'])
df=df_feature_iris
df.head()

用語について

pandasで使う用語で
・行
・列

がある。pandasは行列のmatrix形式で扱ので、ググればすぐわかるが、
行=>縦
列=>横
と考えると分かりやすい

行が横方向にならんだものを示し、列が縦方向にならんだものを示す。表計算ソフトでも、横方向を行と言い、縦方向を列と言う(参考Wikipedia


pandas機能(1~19)


機能1
==行の複数条件指定==

これは列の内容で2つ以上の条件を指定する方法。

・純粋に&で指定するもの
SQLのクエリのように指定する方法
の2つがある。クエリライクのやり方はkaggleで人気

df[(df['sepal_length']>=7)&(df['sepal_width']>=3)]

#またはクエリのように指定する方法
df.query("sepal_length>=7 and sepal_width>=3")


機能2
==特定の型の列のみ取得==

列方向で特定のデータ型の値を取得する
pandasの場合、データ型は「整数('int')・小数('float')・真偽値('bool')」以外は全て「’object'」で指定

df.select_dtypes(['float']).head()


機能3
==列Aごとに列Bを集計する==

列Aのグループを作り、その値内で、列Bの値の数を集計する。

→irisデータで試す
'sepal_length'の列でグループを作り(4.3〜7.9)、'sepal_width'の値(2.0~4.4)を
値ごとに集計

df.groupby('sepal_length')['sepal_width'].value_counts().unstack().head()

‘sepal_length'が4.5で'sepal_width'が2.3の数=>1




機能4
==2つの列A、Bに着目し、3つ目の列Cの値を集計する==

これはわかりにくいので、irisデータで試した。


'sepal_length'でグループを作り(4.3〜7.9)、'sepal_width'の値(2.0~4.4)に
該当する'petal_length'の平均値を集計

df.pivot_table(index='sepal_length', columns='sepal_width',values='petal_length', aggfunc=np.mean).head()

‘sepal_length'が4.5で'sepal_width'が2.3の'petal_length'の平均値は1.3



機能5
==特定の型の削除==

「整数('int')・小数('float')・真偽値('bool')、それ以外(’object')」を指定して削除

df.select_dtypes(exclude=np.int)


機能6
==全列の欠損値カウント==

欠損値(Nanのデータ)を数える

print(df.isnull().sum())

機能7
==欠損値の値を置換==

欠損値を別の値に置換する。

例:欠損値を0に置換

df=df.fillna(0)

機能8
==標準化==

データを機械学習のモデルに読み込ませるとき、正規化(標準化)することが多いので、その手法の一つが標準化
numpyとかでもできるが、今回はScikit-learnを使った。

正規化=>データ等々を一定のルール(規則)に基づいて変形し、利用しやすくすること。

標準化=>元データを平均0、標準偏差が1のものに変換する正規化法の一つ

# 標準化
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
dff = sc.fit_transform(df)
dff=pd.DataFrame(dff)

# 列名を元に戻す
listed=list(df.columns)
dff.columns = listed

機能9
==行列内の文字列の末尾のN個削除 (’iraidate'は列名)==

列の文字列の末尾のN個の文字を削除する

b=[]
for i,v in f2.iterrows():
    b.append(str(v['iraidate'])[:3])

# bのDataFrame作成
f=pd.DataFrame(b, columns=['iraidate'])

# 前の同じ行削除
df=df.drop("iraidate", axis=1)

# 横に連結してもとに戻す
df=pd.concat([df, f], axis=1)


機能10
==データの散布図==

Dataframe(df)とplotしたい列名2つを指定

sns.jointplot('kaiin_id','safety_tesuryo', data=df)


pandasデータの散布図の可視化に便利





あとはそのまんまの機能(機能11〜19)

・全列の名前表示

df.columns

・列名の変更

df=df.rename(columns={'last_login_year_cnts1': 'last_login_year_cnt1'})

・列の削除

df=df.drop('列名', axis=1)


・列名の一括変更(df_colum_listに全列名を入れておく)

df.columns=df_colum_list

・地味に全列名の一括変更

df=df.ix[:,['A','B','C']]

・縦にDataFrame(df)を連結

df=pd.concat([df, df2])

・横にDataFrame(df)を連結

df=pd.concat([df, df2], axis=1)

・list(listed)から列名付きで、DataFarame(df)作成

df=pd.DataFrame(listed, columns=['列名'])


・DataFrame(df)をcsvに保存/読み込み

# 保存
df.to_csv('feature.csv')

# 読み込み
df=pd.read_csv('feature.csv')


備忘録もかねてpandasの機能をまとめてみた。使えるものも多いと思うので、気に入ったらストックしておきたい。

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

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


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

 

マーケティング =>流行のブレイクの検出
コンプライアンス  =>情報漏洩/不正検知
・製造系   =>不具合発生検知
・機械系  =>故障検出
・システム運用系  =>障害検出
・ネットワーク運用系  =>トラフィック異常検出
・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


ワードB


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

 

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

ワードB


 
ご覧の通り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に収録されている一曲。とてもカッコいい曲でスピード感、テンポともに悪くない。曲全体の統一感が素晴らしく、シャナ系と違うタイプの名曲。

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






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