天色グラフィティ

機械学習やプログラミングでいろいろ作って遊ぶブログ

pandas + matplotlibで描くヒストグラムいろいろ

データ解析コンペの初期段階では、データを可視化して眺め、特徴を探すという探索的データ分析(EDA)が行われます。

Pythonでデータ分析している場合、可視化にはpandasのプロット機能、もしくはmatplotlibを使うことが多いでしょう。 今回はヒストグラムに絞って、僕が良く使っている書き方を紹介したいと思います。

題材とするデータにはKaggleのTitanicコンペのデータを使うことにしましょう。一部を抜き出してくるとこんな感じのデータになっています。今回はこのAgeの列を可視化してみたいと思います。

data = pd.read_csv('input/train.csv')
data[['Name', 'Age']].head()
Name Age
0 Braund, Mr. Owen Harris 22.0
1 Cumings, Mrs. John Bradley (Florence Briggs Th... 38.0
2 Heikkinen, Miss. Laina 26.0
3 Futrelle, Mrs. Jacques Heath (Lily May Peel) 35.0
4 Allen, Mr. William Henry 35.0
続きを読む

Mac + matplotlibで日本語を表示する

タイトルにMacと入れたのはそれでしか確認していないから。WindowsLinuxでもパスだけ変えれば当てはまるかもしれない。

TL;DR

  1. matplotlibで日本語表示できる.ttfフォントをインストールしましょう
  2. ~/.matplotlib/matplotlibrcに書きましょう
  3. 【重要】~/.matplotlib/fontList*.cache だけでなく ~/.matplotlib/fontList.jsonも削除しましょう
続きを読む

機械学習コンペで使うスニペットたち

メモです。自分がコピペでぺたぺたする用なので随時更新です。

HyperoptでLightGBMモデルをチューニングする

from hyperopt import fmin, hp, tpe

def objective(params):
    params['num_leaves'] = int(params['num_leaves'])
    params['max_depth'] = int(params['max_depth'])
    params['min_data_in_leaf'] = int(params['min_data_in_leaf'])
    
    model = LGBMRegressor(**params, random_state=0, n_jobs=-1)
    
    # calc score
    return score

space = {
    'num_leaves': hp.quniform('num_leaves', 50, 200, 10),
    'max_depth': hp.quniform('max_depth', 3, 10, 1),
    'min_data_in_leaf': hp.quniform('min_data_in_leaf',  5, 25, 2),
    'colsample_bytree': hp.uniform('colsample_bytree', 0.5, 1.0),
    'learning_rate': hp.uniform('learning_rate', 0.03, 0.2),
    'subsample': hp.uniform('subsample', 0.5, 1.0)
}

best = fmin(
    objective,
    space=space,
    algo=tpe.suggest,
    max_evals=200)

SUUMOデータ分析ワークショップで優勝した。

f:id:ejinote:20180416082927p:plain

sankak.jp

SUUMOのデータ分析ワークショップに参加した。結論から書くと優勝した。文字通りの意味である。

コンペ形式でランキングがつくということなので、腕試しのためにラボの同期と一緒に応募した。(ちなみに同期は落ちたので品川の日本酒フェアみたいなやつに行った)

先日参加予定だったscouty主催のSAICONは運営がテストデータの正解を間違って配るというハプニングによって中止になってしまっていたので、大変失礼ながらリクルート住まいのレベル感はどんな感じなんだろう(にやにや)みたいなノリで登録した。

データについてとかはあまり詳しいことは書けないので、ざっくり説明するとkaggleのZillowコンペみたいな不動産価格予測。特徴量は予めかなり用意してくれているのでそれをそのまま使っても十分モデルは作れそうな感じだった。

続きを読む

ARC095に参加した

f:id:ejinote:20180414230737p:plain

ARC095に参加しました。CとDを40分くらいでやっつけて、Eに1時間取り組むも解けず。 レートは9351010になりました。 ようやっとレート4ケタの世界へ。単調増加し続けていきたいものです。

前回の記事:

amalog.hateblo.jp

続きを読む

GCJ 2018 Round1Aに参加した

f:id:ejinote:20180414130120p:plain

Google Code Jam 2018 Round1Aに参加しました。上位1500人がRound2に進めるらしいのですが、結果としては1717位で敢えなく敗退。

まぁ今回で強い人は全員消えるはずなので、Round1Bがんばりましょ。

前回の記事:

amalog.hateblo.jp

振り返り

Waffle Choppers

横方向に累積和を取った後に縦方向に累積和を取ると、左上から任意の点までの長方形に何個チョコチップが含まれているかが分かる(盤面の累積和)。

望ましい分割をするためには、縦だけに注目したときも横だけに注目したときもチョコチップが均等に別れていることが必要。 なので、盤面の累積和の右端列と下端行に着目すると、そもそもうまくいく分割が存在するかが分かる。

うまくいく分割が存在するならそれに従って実際に分割してみて、ちゃんとそれぞれの部分にチョコチップが割り振られているかを累積和を参照しながら確認すれば良い。

解きながら「numpy使いたい!」ってn回叫んだ。

def cumsum(lst):
    res = [0]*len(lst)
    res[0] = lst[0]
    for i in range(1, len(lst)):
        res[i] = res[i-1] + lst[i]
    return res

def cumsum2(area):
    height = len(area)
    width = len(area[0])
    res = [[0]*width for _ in range(height)]
    
    for i in range(height):
        for j in range(width):
            if j==0:
                res[i][j] = area[i][j]
            else:
                res[i][j] = res[i][j-1] + area[i][j]

    for i in range(height):
        for j in range(width):
            if i!=0:
                res[i][j] = res[i-1][j] + res[i][j]

    return res

def case(R, C, H, V):
    hcnt = [0]*R
    vcnt = [0]*C
    total = 0
    area = [[0]*C for _ in range(R)]
    
    for i in range(R):
        row = input()
        for j, c in enumerate(row):
            if c=='@':
                area[i][j] = 1
                hcnt[i] += 1
                vcnt[j] += 1
                total += 1

    if total%((H+1)*(V+1))!=0 or total%(H+1)!=0 or total%(V+1)!=0:
        return 'IMPOSSIBLE'

    each = total//((H+1)*(V+1))
    area_cumsum = cumsum2(area)
    h_cumsum = cumsum(hcnt)
    v_cumsum = cumsum(vcnt)

    hcuts = []
    vcuts = []

    for i in range(1, H+2):
        target = total//(H+1)*i
        if target not in h_cumsum:
            return 'IMPOSSIBLE'
        else:
            hcuts.append(h_cumsum.index(target))

    for i in range(1, V+2):
        target = total//(V+1)*i 
        if target not in v_cumsum:
            return 'IMPOSSIBLE'
        else:
            vcuts.append(v_cumsum.index(target))
    
    for i, hcut in enumerate(hcuts):
        for j, vcut in enumerate(vcuts):
            if area_cumsum[hcut][vcut] != each*((i+1)*(j+1)):
                return 'IMPOSSIBLE'

    return 'POSSIBLE'


def main():
    T = int(input())
    for t in range(1, T+1):
        R, C, H, V = map(int, input().split())
        print('Case #{}: {}'.format(t, case(R, C, H, V)))

if __name__=='__main__':
    main()

Bit Party

貪欲っぽくとけば良さそうだなーと思った時点で頭が止まったので飛ばした。貪欲っぽく解けば良かったらしい。無念。

Edgy Baking

区間を持っておくDPで解けば良さそうだと思ったが、時間がなかったのでvisible setだけ通る嘘解法(貪欲)を提出した。

反省

  • 実装力が低い。特に少しひねられたDPとかで頭が止まるのをなんとかしたい。atcoderのtypical dp contestとかを解いて出直してきます。

今日はABC・ARCもあるので競プロ漬けの1日にしましょう。