読者です 読者をやめる 読者になる 読者になる

データ・サイエンティストは可視化の夢を見るか?

Does Data Scientist Dream of Visualization?

いちから実装してみる

今夜はあまり眠れなかったので調べ物をしてみたのです。
此の界隈の有名人(?)TJO 氏のブログで、O'reily の『集合知プログラミング』という古い本を見掛けました。解説によると、いちからスクラッチしてアルゴリズムを実装するとのこと、ものすごく興味を惹かれました。

そこで Amazon に買いに行ったんですが、検索すると別の本も候補に——。

Data Science from Scratch

Data Science from Scratch

Data Science from Scratch: First Principles with Python

Data Science from Scratch: First Principles with Python


これはもうやってみるしかないでしょ、って感じで早速購入しました。

パラパラとめくると、基本的な統計関数から丁寧に実装するコードが Python で書かれています。Good ですね。しばらく、これに挑戦してみましょう。


ちなみに、わたしは『車輪の再発明』に否定的です。素人が再実装することであたらしいバグを埋め込んでしまう副作用が考えられますから。それにいまどき開発者側は TDD に則って、きっちりと単体テストをしてきているものです。一昔前だったらブラックボックスになったコードを徹底的に疑う価値もあったんでしょうが………。
でも、『学習』という観点からは「車輪の再発明」は有効な手段ですよね。
そのような次第で、しばらく写経に勤しみます。


(追記:第 8 章までざっくりと写経を進めました。此処でちょっと引っ掛かったことが。Python3 から range() や map() の仕様に変更があって list に自動展開してくれません。此の問題を解消するには list(range()) のようにして強制的にリスト化してやる必要があります。為念。)


(御参考までに本書に登場するコードを。)

def mean(x):
    return sum(x) / len(x)

def median(v):
    """finds the 'middle-most' value of v"""
    n = len(v)
    sorted_v = sorted(v)
    midpoint = n // 2

    if n % 2 == 1:
        # if odd, return the middle value
        return sorted_v[midpoint]
    else:
        # if even, return the average of the middle values
        lo = midpoint - 1
        hi = midpoint
        return (sorted_v[lo] + sorted_v[hi]) / 2

def quantile(x, p):
    """returns the pth-percentile value in x"""
    p_index = int(p * len(x))
    return sorted(x)[p_index]

def mode(x):
    """returns a list, might be more than one mode"""
    counts = Counter(x)
    max_count = max(counts.values())
    return [x_i for x_i, count in counts.items()
            if count == max_count]

# "range" already means something in Python, so we'll use a different name
def data_range(x):
    return max(x) - min(x)

def de_mean(x):
    """translate x by subtracting its mean (so the result has mean 0)"""
    x_bar = mean(x)
    return [x_i - x_bar for x_i in x]

def variance(x):
    """assumes x has at least two elements"""
    n = len(x)
    deviations = de_mean(x)
    return sum_of_squares(deviations) / (n - 1)

def standard_deviation(x):
    return math.sqrt(variance(x))

def interquantile_range(x):
    return quantile(x, 0.75) - quantile(x, 0.25)

def covariance(x, y):
    n = len(x)
    return dot(de_mean(x), de_mean(y)) / (n - 1)

def correlation(x, y):
    stdev_x = standard_deviation(x)
    stdev_y = standard_deviation(y)
    if stdev_x > 0 and stdev_y > 0:
        return covariance(x, y) / stdev_x / stdev_y
    else:
        return 0 # if no variation, correlation is zero