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

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

螺旋本をPythonで解く Part2

  • はじめに
  • 8章 木
    • P188 ALDS1_7_A: Rooted Trees
    • P193 ALDS1_7_B: Binary Tree
    • P198 ALDS1_7_C: Tree Walk
    • P203 ALDS1_7_D: Reconstruction of the Tree
  • 9章 二分探索木
    • P209 ALDS1_8_A: Binary Search Tree 1
    • P214 ALDS1_8_B: Binary Search Tree 2
    • P217 ALDS1_8_C: Binary Search Tree 3
  • 10章 ヒープ
    • P234 ALDS1_9_A: Complete Binary Tree
    • P236 ALDS1_9_B: Maximum Heap
    • P240 ALDS1_9_C: Priority Queue
  • 11章 動的計画法
  • 12章 グラフ
    • P269 ALDS1_11_A: Graph
    • P273 ALDS1_11_B: Depth First Search
    • P282 ALDS1_11_C: Breadth First Search
    • P287 ALDS1_11_D: Connected Components
  • 13章 重み付きグラフ
    • P296 ALDS1_12_A: Minimum Spanning Tree
    • P302 ALDS1_12_B: Single Source Shortest Path 1
    • P309 ALDS1_12_C: Single Source Shortest Path 2
  • つづく
続きを読む

螺旋本をPythonで解く Part1

  • はじめに
  • 2章 アルゴリズムと計算量
    • P46 ALDS1_1_D: Maximum Profit
  • 3章 初等的整列
  • 4章 データ構造
    • P82 ALDS1_3_A: Stack
    • P87 ALDS1_3_B: Queue
    • P95 ALDS1_3_C: Doubly Linked List
    • P114 ALDS1_3_D: Areas on the Cross-Section Diagram
  • 5章 探索
    • P119 ALDS1_4_A: Linear Search
    • P122 ALDS1_4_B: Binary Search
    • P127 ALDS1_4_C: Dictionary
    • P136 ALDs1_4_D: Allocation
  • 6章 再帰・分割統治法
    • P142 ALDS1_5_A: Exhaustive Search
    • P146 ALDS1_5_C: Koch Curve
  • 7章 高等的整列
    • P152 ALDS1_5_B: Merge Sort
    • P158 ALDS1_6_B: Partition
    • P163 ALDS1_6_C: Quick Sort
    • P168 ALDS1_6_A: Counting Sort
    • P175 ALDS1_5_D: The Number of Inversions
    • P179 ALDS1_6_D: Minimum Cost Sort
  • つづく
続きを読む

中心極限定理による分布収束のアニメーション nを増やすと標本平均はどうばらつくか

f:id:aotamasaki:20191011122748p:plain

モチベーション

中心極限定理は一言で言うと、「平均する対象を増やすと、その標本平均は正規分布に従うようになる」という定理である。これの解釈はあとで与える。 この定理は直感的にはわかりにくく誤用する人も多いため、twitterでhotなトピックになった。本記事はそれに便乗した形で書いた。

本記事では、中心極限定理の直感的解釈を与える。また平均する対象を増やしたときに、標本平均の分布がどのように収束していくのかを可視化する。

続きを読む

特徴量重要度にバイアスが生じる状況ご存知ですか?

f:id:aotamasaki:20190715230720p:plain

なぜこの記事を書いたのか?

決定木をベースにしたアルゴリズムのほとんどに特徴量重要度という指標が存在する。データに対する知識が少ない場合はこの指標を見て特徴量に対する洞察深めることができる。KaggleではEDAのときにとりあえず重要度を見てみるなんてこともするようだ。

しかし、この特徴量重要度にはバイアスが存在していて、特定の条件下では信用出来ないことがある。そういった条件を広く知ってほしいということでこの記事を書いた。

この記事では人工データを生成しバイアスを再現してみた。また、こういったバイアスに対処したという論文を見つけたので軽く紹介する。おまけとしてgainベース以外の特徴量重要度についても紹介する。

目次

  • なぜこの記事を書いたのか?
  • 想定読者と実験の枠組み
    • 想定読者
    • 限定する枠組み
  • 特徴量重要度とは?
  • 特徴量重要度にバイアスが生じる条件
    • 1. 解像度が低い場合
    • 2. 特徴量同士にdependancyがある場合
  • 実験
    • 実験設定
    • データの解像度が低い場合
      • データ生成の設定
      • 結果
    • 特徴量同士にdependancyがある場合
      • データ生成の設定
      • 結果
    • その他(おまけ)
      • 特徴量の分布でバイアスは生じるか
      • 判別に寄与する状況下ではどうなるの?
  • 特徴量重要度のバイアスに対抗するには?
  • 3種の特徴量重要度
    • split frequency
    • gini importances
    • permutation importances
  • まとめ
  • 2020/09/06 追記
  • 参考
続きを読む

AI・機械学習ハンズオン 〜実践Kaggle 初級編〜に参加しました

はじめに

今回はただの日記です。 AI・機械学習ハンズオン 〜実践Kaggle 初級編〜に参加したので、感想を書く。 これから行く人が知りたいだろう情報も書くように心がける。

  • はじめに
  • 率直な感想
  • 対象者は?
  • どんなことをやったのか
    • データと環境
    • データのEDA
    • LightGBM推しがすごい
    • コンペ解法解説
    • Kaggle のシステムの説明
  • 懇親会
  • さいごに
続きを読む

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

概要

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

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

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

  • 概要
  • 分析のモチベーション
    • 目的
  • 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')