学習する天然ニューラルネット

主に機械学習に関する覚書や情報の整理。競プロ水色→Kaggle Master→?

新曲をプレイするとスコアはいくつ? 〜最大値を利用したスコアの分布推定〜

概要

本記事では音楽ゲーム(以下音ゲ)において、曲をプレイすると得られるスコアを確率変数として、その分布を推定することを試みた。 音ゲのスコアは慣習的に最大値のみが保存されるような仕組みになっている。 そのため、曲をプレイすると得られるスコアは一覧として得られない。 得られるデータと言えば、その曲を何回プレイして最高のスコアはいくつだったかだけである。 そこで、本記事では、その最大値から背景にあるスコアの分布を推定することを試みた。

本記事をすらすらと読むためには、大学学部レベルの確率統計を履修している必要がある。

どうやらスマホでは本記事の数式が見切れてしまうようである。スマホの方は横画面にして読んでほしい。

  • 概要
  • 分析のモチベーション
    • 目的
  • SDVXにおけるデータ
  • 分析上の仮定
  • ノーテーションと目的
    • 知っている
    • 知りたい
  • 推定のための定式化
    • 1について
    • 2について
    • 3について
  • 実装
  • 推定結果
    • レベル17
    • レベル18
    • レベル19
    • レベル20
  • 考察
    • 実際の実力と比較して
    • レベルの難易度が反映されているか
  • まとめ
続きを読む

PriorityQueue Classを作る [Pythonで競プロ]

この問題を解くのにpriority queueを使う方法がある。 atcoder.jp

Pythonでpriority queueを実装するためには2つ方法があるがどちらも欠点がある。

  1. heapqを用いた方法

    • こちらを用いて実装する方が多いと思う。でもめちゃくちゃ使いづらくないですか?
    • これで用意されている関数は、リストに対してin-placeで処理を施す。
    • クラスが用意されていない。
  2. from deque import PriorityQueue を用いた方法

    • クラスが用意されていて1よりも扱いやすいが、2倍ぐらい遅い。
    • 中身が確認できない。(中身でfor を回す等の作業ができない。)

そこで、1をベースにPriorityQueueクラスを用意した。 pushやpopをメソッドとすることで、heapqをそのまま使うよりもスッキリ見やすく実装することができる。 また、インスタンスをそのまま実行するとheapの中身が見られるようにした。

from heapq import heapify, heappop, heappush, heappushpop

class PriorityQueue:
    def __init__(self, heap):
        '''
        heap ... list
        '''
        self.heap = heap
        heapify(self.heap)

    def push(self, item):
        heappush(self.heap, item)

    def pop(self):
        return heappop(self.heap)

    def pushpop(self, item):
        return heappushpop(self.heap, item)

    def __call__(self):
        return self.heap

    def __len__(self):
        return len(self.heap)

冒頭に上げた問題で使い方の具体例を示すと、こう。

import sys
read = sys.stdin.readline

def read_ints():
    return list(map(int, read().split()))

X, Y, Z, K = read_ints()
A = read_ints()
B = read_ints()
C = read_ints()

A.sort(reverse=True)
B.sort(reverse=True)
C.sort(reverse=True)


from heapq import heapify, heappop, heappush, heappushpop

class PriorityQueue:
    def __init__(self, heap):
        '''
        heap ... list
        '''
        self.heap = heap
        heapify(self.heap)

    def push(self, item):
        heappush(self.heap, item)

    def pop(self):
        return heappop(self.heap)

    def pushpop(self, item):
        return heappushpop(self.heap, item)

    def __call__(self):
        return self.heap


heap = []  # ヒープといっても順序を工夫したただのリスト

q = PriorityQueue(heap) #ここでインスタンスを作ってます
q.push((-(A[0] + B[0] + C[0]), 0, 0, 0))

considered = set()
ans = []
for k_th in range(1, K+1):
    heap_max, i, j, k = q.pop() #ここで一番小さな要素(先頭が見られる)を取り出してます
    ans.append(-heap_max)
    for di, dj, dk in zip([1, 0, 0], [0, 1, 0], [0, 0, 1]):
        i_new, j_new, k_new = i + di, j + dj, k + dk
        if i_new >= X or j_new >= Y or k_new >= Z:
            continue
        if (i_new, j_new, k_new) in considered:
            continue
        considered.add((i_new, j_new, k_new))
        q.push((-(A[i_new] + B[j_new] + C[k_new]), i_new, j_new, k_new)) #ここで要素の追加を行っています。


print(*ans, sep='\n')

逆パームレストを自作した

  • はじめに
  • 薄すぎるMagic Keyboard
  • 底上げ板を自作
    • サイズを決定する
    • ものを購入
    • 作成
  • パームレスト

はじめに

たまには日記のようなことを書いていこうと思います。

最近キーボードの配列をJISからUSに変更しました。 ためしに3日間使ってみようという感じでUSを使ってみたのですが、予想以上にプログラミングがしやすくてそのままUSを使い続けようと決心しました。

そして、一昨日、家用にApple Magic Keyboardを購入しました(HHKBとかなり迷いました)。

www.apple.com

軽いのでMacbook(JIS)とともに持ち運ぶことも苦じゃないですし、iMacMacBookのペアリングの切り替えもケーブルでつなぎ替えるだけという楽々仕様で満足しています。

ただ一点を除いては。

続きを読む

【具体例つき】scikit-learnを改変しよう ~改変版のinstall方法と改変に必要な知識のリンク集~

f:id:aotamasaki:20190324150113p:plain

はじめに

この記事を読むことで、scikit-learnの中身のコードに改変を加えることができるようになることを期待している。改変に必要な知識も学習できるようリンクを用意してある。そして改変を加えたコードをpipで管理する方法も示した。 最後には具体例として、決定木のfeature_importances_を可視化するメソッドをDecisionTreeClassifierに組み込む。

  • はじめに
    • 本記事をおすすめしない人
  • scikit-learnのディレクトリ構造の俯瞰
  • 開発環境を整える
    • pyenvを用いた方法
    • venvを用いた方法
  • 編集した内容が反映されるようにインストールする
  • 編集に必要な知識
    • Pythonの知識
    • scikit-learn
    • scikit-learn準拠モデル
    • Cythonの知識
  • feature_importances_の可視化をscikit-learnに組み込む
    • どういう可視化か
    • DecisionTreeClassifierの改変
    • 可視化、再訪
  • まとめ
  • ソースコード
続きを読む

読んだ本のレビュー データサイエンス編

  • この記事は?
  • レビュー
  • 今読んでる本
    • 現場で使える!PyTorch開発入門
    • Cython Cとの融合によるPythonの高速化

この記事は?

自分が読んだ本を時系列に並べて、独断と偏見で簡単にレビューしていきます。 データサイエンス(機械学習)のスキルが身につくと謳っている本が量産されている中、どの本を読むべきか読まないべきか、という判断の一助になるよう願っています。

この記事は新しい本を読むたびに随時更新していくつもりです。 なお各レビューには以下の点について述べています。

  • 読んだときの事前知識 ... 評価は事前知識によって大きくバイアスがかかると思うので
  • 良い点
  • 悪い点
  • おすすめしない人 ... これに該当しない方は購入して損はないと思います。

またサンプルコードがある場合はリポジトリを載せています。

続きを読む

RNNを用いた正規分布の回帰 keras実装

概要

  • 時系列の1時刻後の分布を推定した
  • パラメーターが時間に依存する正規分布を仮定した
  • ニューラルネット正規分布のパラメーターを学習できるように適切な損失関数を導入した
  • 概要
  • 問題意識
  • データと今回の目的
    • データ
    • 目的
  • 仮定
  • モデル
  • 損失関数
  • 結果
  • 損失関数の導出
  • まとめ
  • あとがき
続きを読む

特徴量選択の今とこれから

  • 特徴量選択とは
    • 特徴量選択の難しさ
    • 特徴量選択の手法の大別
  • 教師ありの特徴量選択
    • filter method
      • 単変量とクラスラベルの関連性を上げる
      • 関係性を上げて冗長性を下げる
      • 関係性を上げて多様性を上げる
    • wrapper method
    • embedding method
  • 特徴量選択のこれから
    • 超高次元データと特徴量選択のアンサンブル
    • 不均衡データにおける特徴量
    • オンライン特徴量選択
    • 深層学習を用いた特徴量選択
  • 最後に

特徴量選択とは

特徴量選択(Feature Selection, 変数選択とも)はデータサイエンスにおいて非常に重要である。

例えば、製造業において欠陥品を判別するタスクを考えてみよう。 このタスクは本当に欠陥品を判別するだけがゴールなのだろうか。 本当に知りたいのは欠陥品がどうして生じるか、という点だろう。 例えば、欠陥品と関係のあるセンサーや工程と提示できたら専門家たちはそこを改良し欠陥品をそもそも生み出さずに済むことができる。 これが本当のゴールである。

ここで重要なのが特徴量選択である。

また、良い特徴量選択は以下の恩恵が期待できる。

  • 学習時間を減らせる
  • モデルの解釈性が向上する
  • モデルの精度が向上する
  • 過学習を減らせる

以前に当ブログでも特徴量選択のまとめのような記事を書いた。

aotamasaki.hatenablog.com

これはかなり初心者向けの内容になってしまったが今回は、もっと踏み込んだ内容にしようと思う。 具体的には、特徴量選択の手法の全体像を紹介してから、需要が大きいとされる教師ありの特徴量選択について代表的な手法とライブラリをいくつか紹介する。 また、最後に最新の特徴量選択の動向も紹介する。

今回紹介する半分以上の内容は、こちらのサーベイ論文にあるので興味がある方はどうぞ。

https://www.researchgate.net/publication/323661651_Feature_selection_in_machine_learning_A_new_perspective

本記事の想定読者は大学学部レベルの機械学習、確率統計、情報理論をかじったことのある方であるが、初学者にも伝わる部分があるように努力した。

特徴量選択の難しさ

例えば、100特徴量から最適な特徴量の部分集合を見つけろ、という問題は、2^{100 } - 1通り試すことになる。 1通りあたり1秒で学習が終わるとしても、全通り試すには宇宙誕生から今までをあと2^{41} (2200億)回繰り返さなければいけない計算になる(宇宙の年齢を2^{59}秒ほどとした)。 最適な特徴量の部分集合を選ぶというのは実質不可能に近い。 この状況の中で、いかに最適な組み合わせに近いものを選択できるか、というのが特徴量選択の難しさである。

続きを読む