プロクラシスト

今日の寄り道 明日の近道

【Day-8】絶望的なデータを前処理で何とかする。(pandas/sklearn)

f:id:imslotter:20171208163632p:plain データ分析ガチ勉強アドベントカレンダー 8日目。

Day-7の記事で、データを取り扱えるようになりました。 しかし、データがいつもきれいで美しいものだとは限りません。なかには絶望的なデータもたくさんあります。

機械学習等の学習器に投げ入れるには、もうひと工夫いることのほうが多いです。 pandassklearnで、できる工夫、前処理についてまとめて行きます

前処理とは

学習の流れを簡単な図にまとめてみる。

データ分析の労力の7~8割は、↑図の赤の部分、前処理といわれている。 適当に学習器に投げ入れたデータよりも、きちんと温かみをもって処理をすることが大事。*1

データをうまく整形することで精度が大きく変わってくるので、試行錯誤で調整を繰り返すことが多い。

ひとくちに前処理といってもデータの質、型(数値、カテゴリ変数、画像、自然言語)、仮定する分布などで大きく変わるので、一概には言えない。下記スライド(英語)は前処理について詳しく書かれていて、大変勉強になった。

絶望的なデータの入手

たとえば、avent-calendar-2017リポジトリにある、day8-sample.csvを読み込んでみる。

import pandas as pd
df = pd.read_csv("day8-sample.csv", index_col="name")
df

すると、絶望的なデータを手に入れることができる。

     height weight
name              
A     160cm   49kg
B     170cm   37kg
C     1.81m     80
D       NaN   50kg
E     1.90m     80
F     170cm    NaN
G     150cm     40

単位が違う、、単位がない、、、NaN。。。 実際、こんなデータがたくさん入っていたりする。本当はオペレーションのレベルで何とかしておけばこんなことは起こらないはずだが、データを集めているヒトが必ずしも情報技術者というわけではない。めんどくさいが、せむかたなし。

データを統一的な型(数値等)に変換(df.apply)

こういうデータを、学習器に投げるための形にもっていくのが、まず始めに行う前処理である。pandasを使えば、比較的楽に処理が可能。

【Day-4】都道府県のデータをいじりながら、pandasを学ぶにて、pandasについて触れた。 ここで、緯度経度を60度法から数値に変換するという処理をしたが、これも前処理のひとつである。 自分で関数を書いてpandasのapply関数を使うと、処理が簡単に行えるので良い。(詳しくはDay-4)

データを眺めると、単位で場合わけしながら、cmとkgに統一した数値データにするのがよさげ。なので、関数を作る。少し雑だが、cm,m,kgなどをうまく除去するように場合わけをする。

def height_to_num(height):
    if type(height)==float:
        return height
    if "cm" in height:
        height = float(height[:-2])
    if (type(height)!=float) and ("m" in height):
        height = float(height[:-1])
        height *= 100
    return height

def weight_to_num(weight):
    if type(weight)==float:
        return weight
    if  (type(weight)!=float) and ("kg" in weight):
        weight = weight[:-2]
    return float(weight)

この関数を全部のindexに適用するのが、apply関数である。次のようにすると、各カラムにさっき作った関数が実行される

df["height"] = df.height.apply(height_to_num)
df["weight"] = df.weight.apply(weight_to_num)
print(df)

出力

      height weight
name               
A      160.0     49
B      170.0     37
C      181.0     80
D        NaN     50
E      190.0     80
F      170.0    NaN
G      150.0     40

数字がきれいに扱えるようになった。

NaNの除去

これで全部統一的なデータ形式にできた。あと厄介なのがNaN(空白)の取り扱い。これをそのまま学習器に代入するとエラーが出る。sklearnでもpandasでも可能である。両方やってみる pandasの場合、下記の三種類がある

  • df.dropna() : NaNのある行を除去
  • df.fillna() : NaNをある値で埋める
  • df.interpolate() : NaNを前後の値から補間

df.dropna()

print(df.dropna(how="any"))

実行すると、

      height  weight
name                
A      160.0    49.0
B      170.0    37.0
C      181.0    80.0
E      190.0    80.0
G      150.0    40.0

このように、ひとつでもNaNが入っているindexは消える。 dropna()内の引数で、消し方を決められる。how="all"だと、すべてNaNのindexだけ消すといった具合になる。 詳しくはこちら

df.fillna()

値を埋める。0で埋めてもいいが、たとえばそのほかの値の統計値を使って埋める。なども可能。今回は平均(mean)で埋めてみる

df.height = df.height.fillna(df.height.mean())
df.weight = df.weight.fillna(df.weight.mean())
print(df)

出力は

name                    
A     160.000000    49.0
B     170.000000    37.0
C     181.000000    80.0
D     170.166667    50.0
E     190.000000    80.0
F     170.000000    56.0
G     150.000000    40.0

ふむふむ、無事平均値で埋まったようだ。ほかにも中央値で埋めるなど、無難な値で埋めることができる。

df.interpolate()

値を近似して補間してしまう方法。indexが意味を持つとき(たとえば時系列などにはよく用いられるが、名前のような、カテゴリカルなときは用いてもあまり意味を成さない。けど、練習のためやってみる。

print("orig\n",df.height.values)
print("interpolate\n",df.height.interpolate(method='linear').values)

interpolateを行った後は、

orig
 [ 160.  170.  181.   nan  190.  170.  150.]
interpolate
 [ 160.   170.   181.   185.5  190.   170.   150. ]

となり、method="linear"では線形補間が行われたことがわかる。

なお、methodには、いろんな補間形式がある。公式ページに補間の方法とまとめが載っているので、参考にするといいだろう。

また、sklearn.preprocessing.imputerでも、欠損値補間はできるようだ。(Imputer)

その他

そのほかにも、回帰代入法など、NaNを埋める方法はたくさんある。データの特徴をみながら、どういう埋め方が良いのかを判断すると良い。

スケーリング

これですべて数値で埋まった値が帰ってきたが、身長と体重で絶対値が違う。こういうデータの大きさ、形状を調節して同じような大きさにするほうが、うまくいく(ことが多い)。これをスケーリングという。

sklearn.preprpcessingには、スケーリングを行う関数が多く実装されている。 sklearn.preprocessing(公式ページ)

StandardScaler

各カラムの値を、平均0、標準偏差1の分布に変えてしまう。データが普通の分布(正規分布っぽい分布)をしているときなどはコレを用いることが多い。skelarn.preprocessing.StandardScalerを用いる。

# standard scaler
# スケールの取り出し(新しいデータが来たときに、固定された正規化定数で対応が可能)
scaler = preprocessing.StandardScaler().fit(df)
# スケールを出す
print("mean:{} std:{}".format(scaler.mean_,scaler.scale_))
# スケーリングを行う
df_scaled = scaler.transform(df)
print(df_scaled)

出力

mean:[ 170.16666667   56.        ] std:[ 12.07614729  16.27443218]
[[-0.84187998 -0.43012253]
 [-0.01380131 -1.16747545]
 [ 0.89708523  1.47470583]
 [ 0.         -0.36867646]
 [ 1.64235603  1.47470583]
 [-0.01380131  0.        ]
 [-1.66995865 -0.98313722]]

基本的には、

  • scaler = preprocessing.hogehoge().fit(df) で、それぞれのアルゴリズムによるデータのスケーリング定数を算出
  • scaler.hoge_で、スケーリング定数を取り出す
  • sceler.transform(df) で、スケーリングした配列を出力

という設計になっている。hogehoge,hogeは各アルゴリズムによって変わってくる

MinMaxScaler

これも良く使うスケーリング方法で、最低が0、最高が1にスケーリングする。StandardScalerとほとんど同じだが、係数が少し変わってくる

# min-max scaling
scaler = preprocessing.MinMaxScaler().fit(df)
print("max:{}, min:{}".format(scaler.data_max_, scaler.data_min_))
print("SCALED")
print(scaler.transform(df))

出力

max:[ 190.   80.], min:[ 150.   37.]
SCALED
[[ 0.25        0.27906977]
 [ 0.5         0.        ]
 [ 0.775       1.        ]
 [ 0.50416667  0.30232558]
 [ 1.          1.        ]
 [ 0.5         0.44186047]
 [ 0.          0.06976744]]

その他

preprocessingには、カーネル向けの前処理(KernelCenterer)や、多項式化(PolynomialFeatures)、バイナリ化(Binarizer)そのほかにもさまざまな前処理方法が用意されている。詳しくは公式ページを参照し、いろいろ試してみるのがいい。使い方は基本的に上記で示したとおり。

また、FunctionTransformerという関数を用いれば、sklearnの設計どおりに自分で特徴量変換関数を作ることができる。たとえば、データにlogをつけることも結構あったりするので、そういう変換関数を作る。

from sklearn.preprocessing import FunctionTransformer
# logを当てはめる
transformer = FunctionTransformer(np.log1p)
transformer.transform(df)

出力は

array([[ 5.08140436,  3.91202301],
       [ 5.14166356,  3.63758616],
       [ 5.20400669,  4.39444915],
       [ 5.14263774,  3.93182563],
       [ 5.25227343,  4.39444915],
       [ 5.14166356,  4.04305127],
       [ 5.01727984,  3.71357207]])

オレオレ特徴変換をしたいときは、こんなのもよさそう。

まとめ

手に入るデータがいつもきれいだとは限らない。というか、汚いぐちゃぐちゃなデータのほうが多い。 うまく変換する方法を知っておくことで、効率的に学習器にデータを投げることができる。

  • pandasのapply関数で、カラムごと一括処理
  • pandasのdropna, fillna, interpolateで、欠損値に対応
  • sklearn.preprocessingをうまく使って、データをいい具合に変換
  • 近年ではよく使うものは、前処理を済ませたデータを配ろうとする動きもあるみたいで、オープンソースとして提供しようとする試みもある。 このdataset.jpというところなどがそう。開発が滞っているっぽいので、活発になればうれしいな(面倒が減るな)とか思ってる。

    データ分析や機械学習に欠かせない「前処理」の共通化を目指したオープンソースが国内で発足|アイザック株式会社のプレスリリース

    以上、これで学習器に投げられるところまできた気がする。 明日は、良い学習器を選ぶためには?というお題で書きたい。

    *1:ディープラーニングの対等で、適当に投げてもかまわんという風潮もあるが、個人的には前処理は結果の説明のために必要だと思っている。

    【Day-7】sklearnで機械学習用データの作り方/使い方をまとめる(sklearn.datasets)

    f:id:imslotter:20171206182003p:plain データ分析ガチ勉強アドベントカレンダー7日目。 今日からはscikit-learnを取り扱う。

    機械学習の主要ライブラリであるscikit-learn(sklearn)。機械学習のイメージをつかみ練習するにはコレが一番よいのではないかと思われる。

    今日はデータを作って、(必要ならば)変形し、モデルに入力するまでをまとめる。

    • 既存データへのアクセスの仕方
    • ある程度狙ったランダムデータを作る方法
    • modelに入力する際、どういう構造でデータを入れるかについて。

    基本的にはDataset loading utilitiesを参考にしながら。 いくつかデータセットをピックアップして、実際に扱ってみる。

    なお、今回はsklearn.datasetsをふんだんに用いるので、はじめに下記コマンドを読み込んでおく。

    from sklearn import datasets
    

    Toy Dataset

    datasets.load_hogehoge()という関数により、データを使うことができる。

    感覚をつかむために用意されたデータセット。簡単に使えるが、デー多数は少なく、学習器の性能をテストするには完全な量ではない。

    スペック

    dataset どういうデータか データ数 次元 特徴量の型 正解ラベル
    load_boston ボストンの家賃 506 13 正の実数 実数
    load_iris アヤメの分類 50×3クラス 4 正の実数 3クラス
    load_diabetes 糖尿病患者の進行状況 442 10 -2<x<2 25~346の整数
    load_digits 8×8ピクセルの数字データ (約)180×10クラス 64 0~16の整数 0から9まで
    load_linnerud 男性の生理学的特徴と運動能力の関係 20 3 整数 整数
    load_wine ワインを3種類に分類 [59,71,48]=178 13 正の実数 3クラス
    load_breast_canser 乳がんの陰性/陽性判定 [212,357]=569 30 正の実数 2クラス

    データの形式

    正解ラベルが実数かクラスかによって、正解データの利用の仕方が回帰か分類かに分かれる。

    ざっくり回帰は、次の値を予測する、分類は、そのデータがどのクラスに属するかを判定する。正解ラベルが実数ならばその値自身に意味があるが、クラス(1,2,3など)ならば、その値自身には意味がない(カテゴリ変数とも呼ばれる)

    先ほどの表で、正解ラベル次第でデータの保持形式が変わる

    正解ラベルが実数

    下記データを保持している

    • data : データに入っているベクトルの値
    • feature_names : 各要素の名前
    • target : 実数値

    (例:boston)

    data =  datasets.load_boston()
    print("data shape:", data.data.shape)
    print("feature name:",data.feature_names)
    print("target value:", data.target)
    

    出力

    data shape: (506, 13)
    feature name: ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT']
    target value: [ 24.   21.6  34.7  ...  22.   11.9]

    正解ラベルがクラス

    下記データを保持

    • data : データに入っているベクトルの値
    • feature_names : 各要素の名前
    • target : クラス(カテゴリ変数)
    • target_names : クラスの名前
    data = datasets.load_iris()
    print("data shape:",data.data.shape)
    print("feature name:",data.feature_names)
    print("target class", data.target)
    print("class name:",data.target_names)
    

    出力

    data shape: (150, 4)
    feature name: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
    target class [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
    class name: ['setosa' 'versicolor' 'virginica']

    シャッフル

    ちなみにこのままだと、データが0,1,2ときれいに並びすぎている。逐次学習のアルゴリズムのときなどは影響を受けてしまうので、sklearn.util.shuffleを用いるとよい

    from sklearn.utils import shuffle
    X, y = shuffle(data.data,data.target, random_state=0)
    print("target class", y)
    

    出力

    target class: [2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0 1 1 1 2 0 2 0 0 1 2 2 2 2 1 2 1 1 2 2 2 2 1 2 1 0 2 1 1 1 1 2 0 0 2 1 0 0 1 0 2 1 0 1 2 1 0 2 2 2 2 0 0 2 2 0 2 0 2 2 0 0 2 0 0 0 1 2 2 0 0 0 1 1 0 0 1 0 2 1 2 1 0 2 0 2 0 0 2 0 2 1 1 1 2 2 1 1 0 1 2 2 0 1 1 1 1 0 0 0 2 1 2 0]

    狙ったランダムデータを生成する

    ラベル付データ生成

    make_hogeを使えば、簡単にデータを生成することができる。hogeで表内囲まれているところは、パラメータで調節できるところ。

    dataset どういうデータか データ数 次元 クラス数 データ分布の調整
    make_blobs ガウス分布のデータ生成
    (重ならない)
    n_samples n_features centers cluster_std
    center_box
    make_classification n-class分類用データ生成
    (詳細設計可能)
    n_samples n_features n_classes 結構複雑
    詳細
    make_gaussian_quantiles 同心円状の分布を生成 n_samples n_features n_classes mean
    cov
    make_hastie_10_2 Hastie Exampleで用いられた分布 n_samples 10 2 -
    make_circles 円の分布 n_samples 2 2 factor
    make_moons 三日月形の分布 n_samples 2 2 -

    その他

    • shuffle(bool) : サンプルをシャッフルするかどうか。

    それぞれのデータの分布(イメージ)はこんな感じ

    f:id:imslotter:20171206190749p:plain

    マルチラベルデータ生成

    さっきのが、正解ラベルがひとつのラベルのとき。正解ラベルを複数持つデータについてはmake_multilabel_classificationにて生成が可能(詳細)。重要なパラメータは下記

    • n_samples, n_features : ↑と一緒
    • n_classes : クラスの数
    • n_labels : ひとつのデータに対するラベル付けするクラスの平均

    ひとつのデータに対して出てくる出力は下記のようになる

    data, target = datasets.make_multilabel_classification(n_samples=100, n_features=10, n_classes=5, n_labels=3)
    print("data:",data[0])
    print("label:",target[0])
    

    出力

    data: [  4.   2.   9.   3.   4.   5.   3.   6.   1.  10.]
    label: [0 1 1 0 0]

    1がついているのがそのデータについているラベル。

    その他

    そのほかにもbiclustering用のデータや、metrics learning用のデータなどもある

    • make_biclustering
    • make_s_curvemake_swiss_roll(xz平面に射影)

    fetchしてくる

    datasets.fetch_hoghogeで、外部リポジトリにあるデータを保持することも可能。普通にダウンロードに時間がかかるので、必要なときだけ保存するようになっている。下記のようなものがある。

    関数 説明
    datasets.fetch_20newsgroups() 自然言語のデータ、20個のニュースカテゴリに分ける。データ数は11314
    datasets.fetch_20newsgroups_vectorized() 上記の文章を単語に分けてベクトル化(13万次元くらい)
    datasets.fetch_california_housing() カリフォルニアの家の評価(正解値は実数)
    datasets.fetch_kddcup99() KDD99の侵入検知のコンペで用いられたデータ。詳細
    datasets.fetch_lfw_pairs() labeld face in the wild の略。同じ人か違う人かの二値分類詳細
    datasets.fetch_lfw_people() 人の名前を当てる分類問題
    datasets.fetch_mldata("hoge") "hoge"を変えれば、ここにあるデータを良しなにとってこれる
    datasets.fetch_olivetti_faces() AT&Tが作った、CV用データセット
    datasets.fetch_rcv1() Reuters Corpus Volumeの略。80万のデータ、約5万のワードベクトル、13のカテゴリ。マルチラベル
    datasets.fetch_species_distributions() species distributionのデータセット参考

    これも基本的には

    • data : データに入っているベクトルの値
    • feature_names : 各要素の名前
    • target : クラス(カテゴリ変数の場合)
    • target_names : クラスの名前

    がデータとして入っている。自然言語ベクトル化する前とかだったら微妙に違うこともあるが、だいたいはこういう配列なんだと思っていればOK。そんなに難しい構造していないので、ちょっと自分が作った学習器を試したいときに、データだけ呼ぶってのもいいと思う。

    学習させる

    データを用意できたので、最後にデータを投げるところまでまとめて終わりにする。 処理の仕方とか、まあ種々のデータのいじり方は後に回すとして、どうやって入力するかだけ。

    1. データをシャッフルして分割する(sklearn.model_selection.train_test_split)
    2. 学習させる(sklearn.ensemble.RandomForestClassifier)
    3. テストして評価する(accuracy)(sklearn.metrics.accuracy_score)

    取ってきたデータを いろんな学習器があるけれど、sklearnは入出力の関数/型が決まっている

    • model.fit(X,y) : モデルを学習する(教師なしの場合は、ラベルはいらないので、model.fit(X))
    • model.predict(X) : モデルからテストを行う

    irisのデータを読み込んで学習を行うところまでをやってみる

    from sklearn.model_selection import train_test_split
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.metrics import accuracy_score
    
    # データの読み込み
    iris = datasets.load_iris()
    data, target = iris.data, iris.target
    # 学習とテストに分ける
    data_train, data_test, target_train, target_test = train_test_split(data, target, train_size=0.8, random_state=1) 
    # RandomForestを使う
    model = RandomForestClassifier()
    # 学習
    model.fit(data_train, target_train)
    # テストと評価
    target_pred = model.predict(data_test)
    print(accuracy_score(target_test, target_pred))
    

    出力

    0.966666666667

    できた。ランダムフォレスト強い

    まとめ

    今日はデータについてと、一度学習するところまでをまとめてみた。 sklearnのデータセットの形を知り、をうまく使いこなせれば、いろいろと幅が広がりそう。

    今日のコードも、上げているので是非試してみてください。

    github.com

    明日もsklearnの話題!最後に取り扱った学習のところをもうちょっと詳しく書く予定です。お楽しみに~

    【Day-6】ゼロからJupyterの達人に!使い方の総まとめ。

    f:id:imslotter:20171205234021p:plain

    こんにちは、ほけきよです。

    データ分析ガチ勉強アドベントカレンダー6日目。

    当ブログもJupyterに関するメモをたくさん記してきました。 今回は保存版ということで、Jupyterの基礎事項から、ちょっとしたTipsなどを総まとめしておきます。この記事を読めばJupyterの使い心地もかなりUPするでしょう。

    事始

    インストール方法、実際に一通り実行してみるところまで行える。

    www.procrasist.com

    コレだけは知っておくべきチートシート

    以前自分のQiitaで書いたものを+αして再掲。最低限知っておくとよいもの。

    起動

    jupyter notebook

    実行

    shift+Enter

    補完

    然るべきところでtab。そこまで強力でもない

    ショートカット

    最低限覚えておくべきショートカット

    ショートカット 役割
    esc+M マークダウンモード
    esc+Y コードモード
    esc+L 行番号表示
    esc+A セルを上に挿入
    esc+B セルを下に挿入
    esc+DD セルを削除

    % : マジックコマンド

    Jupyterをpythonインタプリタとしてではなくシェルとして扱えるもの。詳しくは公式を。

    Built-in magic command

    マジックコマンドには二種類あって、下記の通り。

    • % : 一行を対象とする
    • %% : セル全体を対象とする

    たとえば、

    • %pdoc, %pdef. %psource, %pfile その後につづくもの(関数、クラスなど)の情報を表示
    • %timeit : 実行時間を表示
    • %run : 指定したpythonスクリプトを読み込んで実行
    • �bug : pdbデバッガを走らせる
    • %quickref : その他マジックコマンドのラインナップを表示

    あたりを覚えておけば便利だろう*1

    ? : イントロスペクション

    オブジェクトの前か後ろに?をつけると、jupyterがその説明をしてくれて、とても便利。(下図)

    なお、escを押せば、この情報は閉じられる。

    エディタとしてのJupyterをかっこよく

    Jupyter themesというライブラリによって、簡単にJupyterのテーマを変えられる。故にモチベがあがる。

    www.procrasist.com

    グラフのインタラクティブな操作

    もともとインタラクティブなJupyterをさらにインタラクティブにする。 パラメータをバーでいじればグラフが変わったりすると、素敵やん?

    下記二点を使えば、おしゃれなグラフの描画が可能!

    • Bokeh : オシャレなグラフ描画ライブラリ
    • ipywidget : インタラクティブにパラメータをぐりぐりする

    www.procrasist.com

    Jupyterでイケてるプレゼンをする

    ここまでくれば相当なJupyter使い。プレゼンもJupyterで作っちゃいましょう。 RISEというライブラリを紹介して、実際にプレゼン資料を作っています。

    www.procrasist.com

    種々のこと

    その他Jupyter界隈で気になることをさらっとまとめておく

    Colaboratory

    Colaboratory

    Googleが作ったクラウド型Jupyter - クラウド上でのJupyterの保管 - 複数人での編集

    を可能にする(参考: 日本語版最速!? jupyter notebookをgoogleが神改造 colaboratoryについてまとめてみた。 - Aidemy Tech Blog)

    Jupyterhub

    Jupyterhub documentation

    複数人でひとつのjupyter notebookを使うときに便利 (JupyterHubの構築 - Qiita)

    まとめ

    Jupyter、使いこなせばpythonの専用エディタとして大活躍できそう。 関数の情報や実行時間まで測れるし、かなり優秀だと思う。

    さて、明日からはscikit-klearnのお勉強。どこからやろうかな。考え中。。。

    *1:最悪最後のquickrefだけでも...w

    【Day-5】Jupyterでできる!イケてるプレゼンスライドの作り方

    f:id:imslotter:20171205031053p:plain

    こんにちは、ほけきよです。

    MSのツールの中でも、パワポだけは優れたツールだと思っているんですよ。 けれど、せっかく技術者ならば、そこら辺も新しいツールを使ってみたいものです。

    最近エンジニア界隈では、reveal.jsを使ってHTMLでプレゼン資料を作っているのをチラホラと見かけます。 あれ、かっこよい。。。

    なので、今回は、Jupyterでプレゼン資料を作る方法`をまとめておきます。

    jupyterをスライドにする(利用編)

    RISEをつかう。

    インストールと設定

    コマンド側はたったこれだけ。簡単、超簡単

    pip install RISE
    jupyter-nbextension install rise --py --sys-prefix
    jupyter-nbextension enable rise --py --sys-prefix

    Jupyterを起動して、 赤枠で囲んだ箇所が現れていれば成功

    使い方

    view->Cell Toolbar->slideshowを選択。スライドショー用の設定画面になる。

    下図のように、プルダウンメニューが出ていればOK、

    メニュー 用途
    Slide スライドで新しいページに切り替える
    Subslide サブスライドを作る(→のページ送りじゃなくて↓のページ送り)
    Flagment 同一スライドで、Enterを押してからスライド表示
    Skip スライドに反映しない
    Note スピーカーノート

    また、そのままではダサいので、体裁を整えたい。 %%HTML<style></style>とかでcssをべた書きがめんどくさいけど一番シンプル。その際は、図のように.rise-enabled .revealをつけておくと、スライドにのみ反映となる。つけないと、jupyter編集画面まで変わってしまう。

    実行

    実際にRISEでプレゼンするとこんな感じになる。題材は昨日のアドベントカレンダー

    出力

    htmlに出力 下記コマンドを入力すると、スライドの形式を保ったまま、htmlファイルが出来上がる

    jupyter nbconvert "day5-jupyter-slide.ipynb" --to slides --reveal-prefix "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.1.0"

    出力されたhtmlファイルは、デフォルトのスライドデザインなので、jupyterの冒頭に書いたcssをコピーして、htmlのスライドが始まる直前の<style></style>の間にはめ込んでやる(はじめのスライドのタイトルなどで検索すると見つかりやすい)

    その際に、enable-riseセレクタは消去する。.revealは残す

    アップロード

    github.ioでは、htmlのスライドも見られるようにできる。 参考記事を見ながら、github pagesにあげてみる

    以下参考記事から抜粋した手順

    • reveal.jsを自分のgithubページにforkして、適当な名前に変更(settingで変更、そのままでもOK)
    • ローカルにforkしたreveal.jsページをcloneする
    • gh-pagesブランチを削除
    git branch -rd origin/gh-pages
    git push origin --delete gh-pages
    • 自分で新しくgh-pagesブランチを作成
    git checkout -b gh-pages
    • index.htmlというhtmlファイルを先ほど出力した自分のスライドに差し替える
    • 上記で作ったブランチにpush
    git push origin gh-pages

    ごり押しではあるが、スライドが作られている (demo page )

    ブログ等htmlで埋め込む

    最後、github.ioのページを何とかしてhtmlで埋め込みたい。

    こういうときは<iframe>タグを使う。

    <center>
    <iframe allowfullscreen="true" allowtransparency="true" frameborder="0" height="596"  mozallowfullscreen="true" src="https://hokekiyoo.github.io/jupyter-slide-demo/#" style="border:0; padding:0; margin:0; background:transparent;" webkitallowfullscreen="true" width="800"></iframe>
    </center>
    

    出力はこんな感じ

    まとめ

    いかがでしたか? Jupyter使いはぜひ使ってみてはいかがでしょうか

    試行錯誤を繰り返しながら色々と作ってみたので、改善点があれば教えていただければ幸いです。

    明日はJupyterネタがだいぶブログ内でまとまってきているので、それを踏まえてJupyterの総ざらいをします。ではでは!

    明日はjupyter!!

    【Day-4】都道府県のデータをいじりながら、pandasを学ぶ

    f:id:imslotter:20171204215003p:plain

    データ分析ガチ勉強アドベントカレンダー4日目。 今日はpandasを取り扱う。

    機械学習系の本にも、numpy、scipy, matplotlibの使い方は載っていても、pandasを載せている本って意外と少ない。 けれど、実際numpyの次くらいによく使う。データを取り扱ったり、計算したりするときにとても便利。一方で、癖があって慣れるまでに時間がかかる。なので、基礎的な事項をまとめておこうと思う。

    今回も、githubにコードや扱うデータを配置している。

    github.com

    都道府県の重心データを使いながら、pandasのお勉強をしようという試みである。

    pandasとは

    配列データの取扱が便利に行える

    • データの取り出し
    • データの操作
    • 統計計算
    • 時系列データの処理

    などを簡単に行えるため、重宝する。

    基礎事項は、公式ページの10 minutes to pandasを参考にすると良い。しかしこれ、確実に10分で終わらない内容となっている。その分濃いのでまあOKとする。

    また、リファレンスとしては下記の本も有用である。pandasの製作者が作っているので、信頼性は高い。

    Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

    Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

    基本事項

    データの読み込み/書き込み

    pandasの使い所としては、自分でデータ配列を作るよりかは、読み込んだcsv等のファイルを取り扱う時のほうが多いので、まずはソレ。pythonの組み込み関数であるcsvを使ってもいいが、pandasのほうがより手軽である。

    # 読み込み(csv)
    df = pd.read_csv("japan.csv", index_col="prefecrue")
    # 書き込み(csv)
    df.to_csv("japan2.csv")
    

    index_colは、インデックスにしたい列のこと。行の指定をするときに最もわかりやすいモノ(専門的に言えば主キーのようなもの?)を指定する。指定しなければ通し番号になる。

    Tips : データの文字コードがアレだと、下記のようなエラーが出るときもある。

    UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 0: invalid start byte

    そういうときは、

    df = pd.read_csv("japan.csv", encoding="shift-jis")
    

    とすると、解決する

    SeriesとDataFrameの作成

    読み込んでしまうと、そのまま表がDataFrameとして保管されるが、時には自ら作る場合もあるだろう。 pandasで用意されているデータ構造は下記のようなものがある。

    種類 特徴
    Series 1次元配列。要素をindexに保管
    DataFrame 2次元配列。行をindex、列をcolumnとして保存する
    Panel 3次元配列 参考

    正直、SeriesとDataFrameだけで良い。Panelは初めて知った。

    下記が、データフレームの作り方である

    # seriesが1次元配列、dataframeが多次元配列
    se = pd.Series([1,3,5,np.nan,6,8])
    print(se)
    # dataframe
    dates = pd.date_range("20130101",periods=6) 
    df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
    

    indexは指定しなければ、通し番号になる。datetimeなどで指定してやると後々時刻の範囲検索などもできるので便利である。

    データの基本的な情報をGetする

    (基本的にDataFrameの話を中心にすすめる)

    こうしてGETしたDataFrameの、基本的な情報は、下記のようにしてアクセスできる

    • df.head(3) # 初めの3つを見る
    • df.tail(3)) # 後の3つを見る
    • df.index # インデックスを確認
    • df.columns # カラムを表示
    • df.values # 中の値をarray形式で表示
    • df.describe() # 統計量(頻度、uniqueな値の個数、max,min,平均、25%点etc...)を表示

    df.valuesまでは、は中身を見るのにどれもよく使う。describeは初めて知った。便利そうだから今後使ってみる。

    データ内部へのアクセス

    DataFrame型へのアクセスは、様々用意されている。が、様々用意されているが故に、どれがどのようなアクセスの仕方だったのか、わかりにくくなっているのも事実である。ここで、どういうアクセスの仕方が可能なのか、まとめておく。

    • 基本
      • df["longtitude] # カラムの値(df.longtitudeでも可能)
      • df[0:3] # indexの指定
    • ラベルで指定 : df.loc
      • df.loc["東京都"] # indexの指定
      • df.loc[:,["longtitude","latitude"]] # columnのみ指定
      • df.loc["東京都",["longtitude","latitude"]] #両方指定
      • df.loc["東京都","longtitude"] # セル一つ分の指定
      • df.at["東京都","longtitude"] # セル一つ分の指定(より高速なアクセスが可能)
    • 位置による指定 ; df.iloc
      • df.iloc[3] # ilocによる行指定
      • df.iloc[3:5, 0:2] # ilocによる行列範囲指定
      • df.iat[1,1] # scalarの値(高速版)
    • 条件検索
      • df = df[(df.index!="沖縄県")&(df.index!="北海道")] # 沖縄と北海道は除外
      • 数値的な条件(>, == など)も可能

    新しいcolumnの追加、計算の適用。

    japanデータは、緯度経度が136:08:07のように、数値で入っていない。なので、この60度法で書かれたものをfloat型に変換し、新しいcolumnを追加したい。columnの追加は以下のような方法で出来る。辞書の追加のようなものだ。

    df["new_column"] = (新しい配列 or Series)
    

    変数の変換には、calc_numberという関数を用意した。

    def calc_number(d_num):
        """
        度であらわされてるのを、小数に変換
        """
        d = d_num.split(":")
        n = int(d[0])+float(d[1])/60+float(d[2])/3600
        return n
    

    さて、問題は、これをlongtitude,latitude関数の全てのindexに適用させるにはどうしたら良いかだ。 方法は2つある。

    • 一度配列を作り直して、新しいcolumnとして追加する
    • apply関数を適用する

    二番目の方法のほうが、シンプル。apply関数をつかうと、指定したcolumn全体に所与の関数を適用してくれる。 さっきのcalc_number関数を適用する

    df["latitude_num"]=df.latitude.apply(calc_number)
    df["longtitude_num"]=df.longtitude.apply(calc_number)
    print(df[df["latitude_num"]>135].index)
    

    出力

    Index(['山梨県', '静岡県', '長野県', '岐阜県', '富山県', '新潟県', '石川県', '栃木県', '群馬県', '埼玉県',
           '福島県', '北海道', '山形県', '福井県', '岩手県', '東京都', '奈良県', '宮城県', '秋田県', '三重県',
           '神奈川県', '青森県', '愛知県', '和歌山県', '滋賀県', '大阪府', '茨城県', '京都府', '千葉県'],

    ちゃんと西の方にある県が取り出せているよう。

    イテレーションを回す

    pandasはイテレーション用のメソッドを持っている。 が、なんかややこしいのでなかなか覚えられない。コチラのサイトを無限回見ている。何度もググって何度もこのページを開くのも流石にアレなので、ここにメモしておく。

    DataFrameなら、下記の3種類のイテレーション方法がある

    http://cdn-ak.f.st-hatena.com/images/fotolife/s/sinhrks/20150618/20150618222231.png
    (StatsFragmentsより引用)

    イテレーションの練習に、各都道府県の重心をプロットしてみる。*1

    plt.figure(figsize=(8,8))
    for key, row in df.loc[:,["longtitude_num","latitude_num"]].iterrows():
        plt.scatter(row["latitude_num"],row["longtitude_num"],
                    marker="x",color="blue")
    

    f:id:imslotter:20171204211523p:plain

    日本地図っぽい点群が出てきた。

    統計計算をしてみる

    今回の最後に、統計計算をpandasでしてみる。 pandasでは、簡単に統計計算を行うことが出来る。例えば以下の様なものが用意されている

    • df.mean() : 平均
    • df.std() : 標準偏差
    • df.var() : 分散
    • df.min() : 最小値
    • df.max() : 最大値

    全国の緯度と経度の平均を取ってみて、先程の都道府県重心プロットに重ね合わせる。どこになると思います?予想してみてください。

    longtitude_mean = df["longtitude_num"].mean()
    latitude_mean = df["latitude_num"].mean()
    print("latitude;{:.2f}, longtitude_mean:{:.2f}".format(latitude_mean, longtitude_mean))
    # >>> latitude;136.01, longtitude_mean:35.34
    

    さっきの日本地図に重ね合わせると

    f:id:imslotter:20171204212326p:plain

    こんな感じ。値をgooglemapで確認すると... f:id:imslotter:20171204212724p:plain

    滋賀県に!

    まとめ

    というわけで、よく使ったり調べたりする事柄を、まとめておいた。*2 しかし、ここに載せているのはpandasの機能のほんの一部分に過ぎない。 もともと金融データを取り扱う用に作られている*3ため、特に時系列データの取扱いは得意なようである*4。そのあたりもどこかでまとめられたらまとめる。

    明日はjupyter!!

    *1:pandasでもplotの関数はあるが、調べるのもめんどくさいので、matplotlibのものを使っている。

    *2:10 minutes to pythonは途中で飽きたので中座。。。

    *3:って書いていた気がする

    *4:rolling関数とか

    【Day-3】知らないコトがいっぱい...!『numpy 100 exercise』を全部やってみる (上級編)

    f:id:imslotter:20171203122846p:plain

    データ分析ガチ勉強アドベントカレンダー3日目。 今日も引き続き、100 numpy exercise をしていく。

    github.com

    今日は上級編。初級、中級でさえかなり難しかったので、不安ではあるが...とりあえずやっていく!

    また、問題の和訳と難易度も掲載しているので、自分の実力を試したい人はどうぞ。 自分が書いたコードともこちらに載せた(day3のやつ)

    github.com

    問題

    以下に、初級中級の問題を掲載する。長いので、ボタンを押すと見られるようにしている。

    • ○ : 模範解答どおり
    • △ : もっと効率的なやり方があった
    • ✕ : わからなかった
    実際の問題をみる
    番号 問題 難易度 結果
    64 2つのベクトルa,bがあって、aベクトルに、bで与えられたインデックスに箇所に1を加える ★★★
    65 aベクトルの値を用いて新しいベクトルを、bのインデックスに従って作る ★★★
    66 dtype=ubyte)の(w,h,3)画像全体を定義し、uniqueな値の数計算する(色はRGB256階調) ★★★
    67 4次元配列において、最後の2軸だけ一気に足す方法は? ★★★
    68 1次元ベクトルaを用意する。aと同じサイズで用意されたインデックスベクトル(min:0, max:9) s に従って構成されるsubsetベクトルの平均 ★★★
    69 内積の対角成分だけを取り出す ★★★
    70 [1,2,3,4,5]に対し、各値の間に3つの連続したゼロが挿入された新しいベクトルを作成する方法は? ★★★
    71 (5,5,3)の行列に対し、(5,5)の行列を、(5,5)の要素の箇所だけ掛け合わせる方法は? ★★★
    72 行列の特定の行を入れ替える ★★★
    73 三角形を記述する10個のtripletsがある。全ての三角形を作る線分の中で、uniqueなモノを書き出す。 ★★★
    74 bincountされた配列Cに対して、np.bincount(A)==CとなるようなAをどう作るか ★★★
    75 array上でsliding windowを使った平均算出法 ★★★
    76 一次元ベクトルaに対して一行目が(a[0],a[1],a[2])となって、以下の行はインデックスを1ずつずらした値が入るような行列をつくる ★★★
    77 配列のbooleanをひっくり返す、floatの記号をひっくり返す ★★★
    78 2つの点p0,p1がある。ある点pにおいて、p0,p1が作る直線と点pの距離を求めよ。 ★★★
    79 点群の集合P0,P1,Pがあって、Pの各要素の点からP0,P1が作る直線の距離を計算して配列にせよ。 ★★★
    80 配列Zに対し、与えられたpositionを配列の中心とし、与えられた形(shape)をくり抜いて新しい配列を作る(ないところは0で埋める) ★★★
    81 a=[1,2,3,4,5,...,14]とした時、R = [[1,2,3,4],[2.3.4.5].[3.4.5.6],...,[11,12,13,14]]を作る方法 ★★★
    82 行列のランクを計算する ★★★
    83 行列の中で最も使われている値を見つける ★★★
    84 (10,10)のランダム行列から全ての連続した(3,3)行列を取り出す ★★★
    85 Z[i,j]==Z[j,i]となるような、2次元配列のサブクラスを作る ★★★
    86 pセットの(n,n)の配列( size=(p,n,n) )と、pセットの(n,1)のベクトル( size = (p,n,1) )を用意する。p個の配列の掛け算を一度に実行する ★★★
    87 (16,16)の配列について、4×4のブロック和を求める ★★★
    88 ライフゲームをnuypyで実装する ★★★
    89 配列の中でn番目に大きな値を取る ★★★
    90 数値ベクトルについて、直積を取る。 ★★★
    91 普通の配列からrecord arrayを作る ★★★
    92 ベクトルaに対し、aの要素を3乗する計算方法を3つ答えよ ★★★
    93 A:(8,3)の配列、B:(2,2)の配列がある。Bの要素の順序は無視して、Bのそれぞれの行の要素を含むAの行を抜き出す ★★★
    94 (10,3)の行列に対し、全ての値が異なるrowとなるmatrix ★★★
    95 整数行列をバイナリ表現で表す ★★★
    96 2次元配列において、uniqueなrowを抽出 ★★★
    97 2つのベクトルa,bを考える。inner、outer、sum、mulの関数を求める ★★★
    98 2つのベクトル(x,y)によって作られるpathにおいて、等間隔サンプリングを用いてサンプリングする ★★★
    99 整数nと二次元配列Xがある。整数のみを含み、また和が4になる行を抜き出す ★★★
    100 1次元配列Xの平均のbootstrapped samplingにおける95%区間を計算する ★★★

    結果

    ★★★になると、題意がわからない問題も増えた。あと、普通に難しい、日本語が*1想像以上に解くのに時間がかかった。

    また、ゴリ押しでなんとかなる問題も結構あった*2。でも美しい回答を心がけたいところである。

    全問題
    37 15 7 15

    活躍したeinsum

    上級で印象に残ったのは、einsumを使う問題が結構多かった。 einsum()というのは、アインシュタインの縮約記号をpythonで使える、便利なやつ。以前記事にもしているので、そちらが詳しい。

    とにかく、**多次元配列や、複雑な配列演算に超絶威力を発揮する。

    下記の問題でeinsum()が使われている

    • (69). 内積の対角成分だけを取り出す
    • (71). (5,5,3)の行列に対し、(5,5)の行列を、(5,5)の要素の箇所だけ掛け合わせる方法は?
    • (84). pセットの(n,n)の配列( size=(p,n,n) )と、pセットの(n,1)のベクトル( size = (p,n,1) )を用意する。p個の配列の掛け算を一度に実行する
    • (90). 数値ベクトルについて、直積を取る。
    • (92). 大きなベクトルaに対し、aの要素を3乗する計算方法を3つ答えよ
    • (97). 2つのベクトルa,bを考える。inner、outer、sum、mulの関数を求める

    更に、実行時間が早くなるという恩恵も受けられる。92.の実行時間を確かめてみる

    x = np.random.rand(5e7)
    %timeit np.power(x,3)
    %timeit x*x*x
    %timeit np.einsum('i,i,i->i',x,x,x)
    

    計算結果

    2.42 s ± 79.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    762 ms ± 118 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    364 ms ± 15.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

    数倍早い。

    物理学徒以外の人は余り馴染みがないと思うので、初めは苦労するかもだが、慣れるととても良い。

    勉強になった問題(抜粋)

    例のごとく、勉強になった問題を抜粋する。

    全問題とちょっとした調べ物のリンクなどは、前と同様にgithubに残した。

    github.com

    81. a=[1,2,3,4,5,...,14]とした時、R = [[1,2,3,4],[2.3.4.5].[3.4.5.6],...,[11,12,13,14]]を作る方法

    普通にゴリ押しでも行けたが、関数を知っていると一発で終わりとても良いので、メモしておく。

    自分の回答

    a = np.arange(1,15,dtype=np.int32)
    b = np.zeros((11,4),dtype=np.int32)
    for i in range(11):
        b[i] = a[i:i+4]
    print(b)
    

    模範解答

    np.lib.stride_tricksを使う stride_trickの説明ページ

    Z = np.arange(1,15,dtype=np.uint32)
    R = np.lib.stride_tricks.as_strided(Z,(11,4),(4,4))
    print(R)
    

    共に出力は以下

    [[ 1  2  3  4]
     [ 2  3  4  5]
     [ 3  4  5  6]
     [ 4  5  6  7]
     [ 5  6  7  8]
     [ 6  7  8  9]
     [ 7  8  9 10]
     [ 8  9 10 11]
     [ 9 10 11 12]
     [10 11 12 13]
     [11 12 13 14]]

    82. 行列のランクを計算

    線形代数パッケージnp.linalgを使う。linalgの説明ページ

    linalgを使うと、例えば以下の様なことが出来る

    • 特異値分解 : np.linalg.svd(A)
    • ノルムを出す : np.linalg.norm(a)
    • 行列式を出す : np.linalg.det(A)
    • 方程式を解く : np.linalg.solve(a,b)
    • 逆行列を出す : np.linalg.inv(A)
    • 固有値を出す : np.linalg.eig(A)
    Z = np.random.uniform(0,1,(10,10))
    U, S, V = np.linalg.svd(Z) # Singular Value Decomposition
    #np.linalg.matrix_rank(Z) も可
    rank = np.sum(S > 1e-10)
    

    83. 行列の中で最も使われている値を見つける

    このbincount()というやつが結構便利。どの値が何個あるかを数えてくれる。 また、重複を避けた配列を返すものはnp.unique(a)というのが便利だったりする

    A = np.random.randint(0,5,10)
    print(A)
    print(np.bincount(A).argmax())
    #unique
    print(np.unique(A))
    

    出力

    [1 1 2 0 3 2 2 1 4 0]
    1
    [0 1 2 3 4]

    95. 整数行列をバイナリ表現で表す

    2進数に直す方法。ゴリ押しでもいけるが、模範解答がエレガントだったので、採用。

    &演算子がバイナリの演算子なのとreshap(-1,1)で縦ベクトルに出来るのを利用する。

    I = np.array([0, 1, 2, 3, 15, 16, 32, 64, 127])
    print(I)
    # print(I.reshape(-1,1))
    # print([3]&(2**np.arange(8))!=0)
    B = ((I.reshape(-1,1) & (2**np.arange(8))) != 0).astype(int)
    print(B[:,::-1])
    

    出力

    [  0   1   2   3  15  16  32  64 127]
    [[0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 1]
     [0 0 0 0 0 0 1 0]
     [0 0 0 0 0 0 1 1]
     [0 0 0 0 1 1 1 1]
     [0 0 0 1 0 0 0 0]
     [0 0 1 0 0 0 0 0]
     [0 1 0 0 0 0 0 0]
     [0 1 1 1 1 1 1 1]]

    まとめ

    2日に渡って、numpyの勉強をしてきた。 結構網羅的だったように思う。知らない関数もだいぶ多かったし、いい勉強になった。

    何よりも、数時間配列を作ってはいじり作ってはいじりを繰り返したお陰で、ささっと配列を作れるよぅになった気がする。これはもう訓練なので、一度こういう時間を儲けられたのはとても良かった。

    というわけでとりあえずnumpyの総ざらいは終わり。次回以降はpandasscikit-learnjupyterの復習・勉強をしていく。それではまた明日!

    *1:和訳が意味不明のものもあると思います、スミマセン。実行してみて何がいいたいか確かめてくださいw

    *2:88.ライフゲームとか

    【Day-2】numpyの勉強に『100 numpy exercise』を全部やってみる(初級・中級編)

    f:id:imslotter:20171202225708p:plain

    データ分析ガチ勉強アドベントカレンダー2日目。 数式を扱うことが多くなるので、numpyの復習をしたいと思う。使ったのは100 numpy exercise

    github.com

    numpyを用いるさまざまな問題が用意されていて、大変勉強になる。 今回は自分の実力を試すために、自分で解きつつ、よく使ったもの/新しく学んだことを列挙していく。

    また、問題の和訳と難易度も掲載しているので、自分の実力を試したい人はどうぞ。 自分が書いたコードともこちらに載せた

    github.com

    2日目は、初級・中級を掲載する。上級は明日挑戦して掲載予定。

    • ★☆☆ : 初級
    • ★★☆ : 中級
    • ★★★ : 上級

    問題

    以下に、初級中級の問題を掲載する。長いので、ボタンを押すと見られるようにしている。

    • ○ : 模範解答どおり
    • △ : もっと効率的なやり方があった
    • ✕ : わからなかった
    実際の問題をみる
    番号 問題 難易度 結果
    1 numpyを`np`という名前でimport ★☆☆
    2 numpyのバージョンとconfigを表示 ★☆☆
    3 サイズ10のnullベクトルを作成 ★☆☆
    4 作った配列のメモリサイズを確認 ★☆☆
    5 コマンドラインからnumpyのドキュメントを見る ★☆☆
    6 サイズが10で5番目の値だけ1の配列を作る ★☆☆
    7 値が10から49まで順に並んだ配列を作る ★☆☆
    8 配列の値をひっくり返す ★☆☆
    9 それぞれ0~8まで入った3×3の行列を作る ★☆☆
    10 [1,2,0,0,4,0]から0じゃない箇所を見つける ★☆☆
    11 3×3の単位行列をつくる ★☆☆
    12 3×3×3の乱数行列を作る ★☆☆
    13 10×10の乱数行列を作って、最大値と最小値を見つける ★☆☆
    14 サイズ30の乱数ベクトルを作って平均値を出す ★☆☆
    15 境界が1で、中身が0の2次元配列をつくる ★☆☆
    16 今ある配列に、0で埋めた境界を作る ★☆☆
    17 np.nanとnp.inf、小数の扱い ★☆☆
    18 5×5の行列を作って、対角成分の一つ下だけ1,2,3,4で埋める ★☆☆
    19 8×8の行列を作り、チェッカーボードパターンを作る ★☆☆
    20 (6,7,8)の配列で、インデックス(x,y,z)における100番目の要素は? ★☆☆
    21 ile functionを使って8×8のチェッカーボードパターンを作る ★☆☆
    22 5×5の乱数行列を正規化する ★☆☆
    23 8ビット整数を使って色を記述するdtypeを作る ★☆☆
    24 5×3の行列と3×2の行列を掛け合わせる(実数) ★☆☆
    25 1次元配列で、3以上8以下の値は負値にする ★☆☆
    26 numpy有無でのsum()の結果はわかる? ★☆☆
    27 整数ベクトルのなかでどの記述が間違っている? ★☆☆
    28 配列のゼロ除算 ★☆☆
    29 配列の小数点以下切り上げ ★☆☆
    30 2つの配列の中から同じ値を見つける ★☆☆
    31 numpyのwarningを無視する ★☆☆
    32 np.sqrtとnp.emath.sqrtの違い ★☆☆
    33 昨日、今日、明日の日付 ★☆☆
    34 2016年7月の日付配列 ★☆☆
    35 要素の計算( (A+B)*(-A/2) )をコピーなしで計算 ★★☆
    36 乱数行列の整数部分だけ取り出すやつ5種類 ★★☆
    37 行の値が[0,1,2,3,4]となる、5×5の行列 ★★☆
    38 ジェネレータを使って0から9までの配列を作る ★★☆
    39 0より大、1より小のサイズ10のrangingベクトルを作る ★★☆
    40 サイズ10のランダム配列を作ってsortする ★★☆
    41 小さい行列をnp.sumより早く計算する方法は? ★★☆
    42 2つのランダムベクトルが等しいかどうかを判定する ★★☆
    43 配列をimmutable(read-only)にする ★★☆
    44 直交座標の10×2の行列を極座標変換 ★★☆
    45 サイズ10のベクトルを作って最大値を0に変換 ★★☆
    46 x,y座標を[0,1]×[0,1]領域に変換したstructured arrayを作る ★★☆
    47 2つのベクトルを用いてコーシー配列(Cij =1/(xi - yj))を作れ ★★☆
    48 それぞれのnumpy scalar typeでの最小、最大値をprintする ★★☆
    49 配列の全ての値を省略せずにプリントする ★★☆
    50 ベクトル内の与えられたvalueの中で最も近い値を出力 ★★☆
    51 位置座標とcolorのRGBが保存されたstructured arrayを作る ★★☆
    52 10×2のランダム行列を作って、点同士の距離を求める ★★☆
    53 float32の行列をint32の行列に変換 ★★☆
    54 どうやってファイルを配列に変換する? ★★☆
    55 numpyの配列のenumerateと同等の表現は? ★★☆
    56 2DのGaussian-like arrayを生成する ★★☆
    57 2次元配列にランダムにp個、値を埋め込む ★★☆
    58 行列の各行に対し、その行の平均を引いていく ★★☆
    59 n列目のcolomunをソート ★★☆
    60 2D arrayにnullがあるかどうかを判定する ★★☆
    61 指定の値に最も近い値を見つける ★★☆
    62 イテレータを使って1×3行列と3×1行列のsumを計算 ★★☆
    63 名前の属性を付与したarrayクラスをつくる ★★☆

    結果

    なかなか厳しい結果となった。厳しい。 初級から結構知らないものが出てきたので、ほーんと思いながらといた。

    中級以降は、ダメ。自分がいかにプリミティブな操作しかできていないんだなというのを痛感した。

    難易度 問題数 正解 正答率
    ★☆☆ 34 23 67%
    ★★☆ 29 12 41%

    numpy配列の基本

    せっかくなので、よく使うnpの関数と、新しく知ったお得機能をメモしておきたい。このあたりを知っておけば、基本的な操作はできると思われる。

    配列を作る

    とりあえず配列を作れないとお話にならないので、作るときに便利な関数たちを列挙

    np.array([1,2,3,4,5])
    #>>>array([1, 2, 3, 4, 5])
    
    np.zeros((3,3))
    #>>>array([[ 0.,  0.,  0.],
    #        [ 0.,  0.,  0.],
    #        [ 0.,  0.,  0.]])
    
    np.ones((3,3))
    #>>>array([[ 1.,  1.,  1.],
    #       [ 1.,  1.,  1.],
    #       [ 1.,  1.,  1.]])
    
    np.random.random(5) #0から1までのランダム変数をサイズ5のベクトルで
    #>>>array([ 0.33732001,  0.73696762,  0.69890914,  0.46966465,  0.91019171])
    
    np.random.randint(0,5,10) #0から4までのランダム整数をサイズ10のベクトルで
    #>>>array([4, 3, 4, 1, 1, 4, 1, 3, 2, 0])
    
    np.random.uniform(0,1,5) #0から1までの一様実数をサイズ5のベクトルで
    #>>>array([ 0.72515655,  0.09389927,  0.49393525,  0.11564103,  0.31317932])
    
    np.random.normal(0,1,(3,3)) #平均0, 分散1の正規分布を3×3の行列で
    #>>>array([[ 0.64296467, -0.14865526, -0.24650383],
    #       [ 0.30479151, -1.61713417, -0.15371185],
    #       [ 0.92736104,  1.58778307, -1.86301156]])
    
    np.arange(10) #0から9まで順番に
    #>>>array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    
    np.arange(1,10,2) #1から10を超える直前の数字まで2個飛ばしで
    #>>>array([1, 3, 5, 7, 9])
    
    np.linspace(0,10,10) #0から10までを5分割
    #>>>array([  0. ,   2.5,   5. ,   7.5,  10. ])
    
    # 5×5の配列の中にx,y座標を埋め込む
    A = np.zeros((5,5), [('x',float),('y',float)])
    A['x'], A['y'] = np.meshgrid(np.linspace(0,1,5),
                                 np.linspace(0,1,5))
    print(A)
    # >>> [[( 0.  ,  0.  ) ( 0.25,  0.  ) ( 0.5 ,  0.  ) ( 0.75,  0.  ) ( 1.  ,  0.  )]
    # [( 0.  ,  0.25) ( 0.25,  0.25) ( 0.5 ,  0.25) ( 0.75,  0.25) ( 1.  ,  0.25)]
    # [( 0.  ,  0.5 ) ( 0.25,  0.5 ) ( 0.5 ,  0.5 ) ( 0.75,  0.5 ) ( 1.  ,  0.5 )]
    # [( 0.  ,  0.75) ( 0.25,  0.75) ( 0.5 ,  0.75) ( 0.75,  0.75) ( 1.  ,  0.75)]
    # [( 0.  ,  1.  ) ( 0.25,  1.  ) ( 0.5 ,  1.  ) ( 0.75,  1.  ) ( 1.  ,  1.  )]]
    
    # イテレータを使って0から9までのサイズ10の配列
    def generate():
        for x in range(10):
            yield x
    a = np.fromiter(generate(),dtype=float,count=-1)
    print(a)
    #>>> [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9.]
    
    # チェッカーフラッグのように、4×4の行列に0,1を並べる
    np.tile(np.array([[0,1],[1,0]]),(2,2))
    #>>> array([[0, 1, 0, 1],
    #            [1, 0, 1, 0],
    #            [0, 1, 0, 1],
    #            [1, 0, 1, 0]])
    

    形を変える

    reshapeを使う

    a = np.arange(10)
    print(a)
    >>>
    a.reshape(2,5)
    >>>
    

    endpointの有無

    linspaceについて、指定した値を以下として扱うか未満として扱うか

    np.linspace(0,10,10)
    #>>> array([  0.        ,   1.11111111,   2.22222222,   3.33333333,
    #           4.44444444,   5.55555556,   6.66666667,   7.77777778,
    #           8.88888889,  10.        ])
    np.linspace(0,10,10,endpoint=False)
    #>>>array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
    

    hstack, vstack, concatenate

    listのappendみたいなもの。ベクトル同士の結合

    a = np.arange(4)
    b = np.arange(4)[::-1]
    print(a,b)
    #>>> [0 1 2 3] [3 2 1 0]
    print(np.hstack((a,b)))
    #>>> [0 1 2 3 3 2 1 0]
    print(np.vstack((a,b)))
    #>>> [[0 1 2 3]
    #     [3 2 1 0]]
    

    スカラー値を足すとどうなる?

    全部に適用される

    a = np.arange(4)
    print(a)
    #>>> [0 1 2 3]
    print(a+1)
    #>>> [1 2 3 4]
    

    勉強になった問題(一部抜粋)

    多くの問題が学びのあるものだったが、個人的に勉強になった問題を抜粋する なお、全問題と回答はgithubにあげている。 とはいえ、中級はかなり勉強になったので、全部試してみると学びが大きいかもしれない。 githubには問題の和訳と回答をあげてみた。自分なりの回答をしているものもある。

    24. 5×3の行列と3×2の行列を掛け合わせる(実数)

    np.dotだけじゃなくて、@なる演算子があるらしい。

    A = np.arange(0,12).reshape(4,3)
    B = np.arange(0,6).reshape(3,2)
    print(A)
    print(B)
    print(A@B)

    出力

    [[ 0  1  2]
     [ 3  4  5]
     [ 6  7  8]
     [ 9 10 11]]
    [[0 1]
     [2 3]
     [4 5]]
    [[10 13]
     [28 40]
     [46 67]

    25. 1次元配列で、3以上8以下の値は負値にする

    条件文で検索をかけることができる

    a = np.arange(15)
    a[(a>3)&(a<=8)] *= -1
    print(a)
    

    出力

    [ 0  1  2  3 -4 -5 -6 -7 -8  9 10 11 12 13 14]

    36. 乱数行列の整数部分だけ取り出すやつを5種類

    //という演算子をはじめて知った。

    Z = np.random.uniform(0,10,10)
    print("36:")
    print(Z - Z%1)                      # 余りを引く
    print(np.floor(Z))                  # 切り捨ての関数
    print(np.ceil(Z)-1)                 # 切り上げて1を引く
    print(Z.astype(int).astype(float))  # 整数にしちゃう
    print(np.trunc(Z))                  # 整数部だけ取り出す
    print(Z//1)                         # 切り捨て演算子
    

    41. 小さい行列をnp.sum()より早く計算する方法は?

    add.reduce()を使うと良いらしい

    a = np.arange(100)
    print(np.add.reduce(a))
    

    43. 配列をimmutable(read-only)にする

    writeableをfalseの設定にして、書込み禁止にする。numpyはその設定ができる

    a43 = np.zeros(10)
    a43.flags.writeable = False
    # a43[0] = 1 エラーが出る
    

    49. 配列の全ての値を省略せずにプリントする

    printoptionsを利用することで、 省略されずに配列の全要素を見ることができる。

    np.set_printoptions(threshold=np.nan)
    x = np.zeros((16,16))
    

    55. numpyの配列のenumerateと同等の表現は?

    通常のenumerateのような、ndenumerate, ndindexというのがある。こっちのほうが早いのかな?あんまり違いがわかっていない。

    A = np.arange(9).reshape(3,3)
    for index, value in np.ndenumerate(A):
        print(index, value)
    for index in np.ndindex(A.shape):
        print(index, A[index])
    

    まとめ

    全然わからないものもたくさんあって、とても勉強になった。 明日は上級(★★★)にチャレンジ予定だが、0点なのではないかと危惧している。 でも、numpyはどういう場面でも使うので、基本をしっかり抑えておきたいなと思う。

    それではまた明日!

    【Day-1】データ分析/機械学習を行うために知っておきたいことを列挙する

    f:id:imslotter:20171201095130p:plain

    データ分析ガチ勉強アドベントカレンダー一日目。 まずは指針をということで、データ分析をはじめるにあたって勉強しておきたいことと、そのリソースをまとめる。言語はPythonを想定。

    • 興味領域が偏っている場合があるのであしからず
    • こんなの面白いよっていうのあれば教えてくださいな

    ※随時更新します

    Pythonライブラリ

    こんなの勉強しておけば良さそうリスト。抜け漏れご容赦。

    • ★★★ : 必須。空で使えるようになりたいトコロ。
    • ★★  : 周辺ツール、知っていればより便利になるよという感じ
    • ★   : あるアルゴリズムに特化しているようなもの。一歩先
    ライブラリ 必須度 用途
    numpy ★★★ 数値計算用のライブラリ。いろいろしてくれる
    scikit-learn ★★★ 機械学習用ライブラリ。たいていの基本的なことはここで出来る
    matplotlib ★★★ グラフ描画用ライブラリ。オシャレさはないけど使いやすい
    pandas ★★★ 表計算用ライブラリ。Excelなんて目じゃない。
    Jupyter ★★★ コード書きながら実験できるのが便利。詳しくはこちら
    scipy ★★ 統計処理の計算ライブラリ。numpyとsklearnで事足りる感は正直ある
    BeautifulSoup ★★ スクレイピング用ライブラリ。オリジナルデータ作成のときは役に立つ
    urllib ★★ クローリング,スクレイピング用ライブラリ
    re ★★ 正規表現ライブラリ。文字列の処理に使う
    json ★★★ jsonファイルの読み書き、パースを行うライブラリ、何かと使うことが多い
    deap 進化計算用ライブラリ。コチラのqiitaが詳しい
    statsmodels 時系列分析用ライブラリ
    prophet facebook謹製の時系列分析用ライブラリ
    opencv ★★ 画像を取り扱うときに使うライブラリ
    pyMC MCMC用ライブラリ、サンプリングがかんたんに出来る。亜種にPyStanもあり
    pycwt wavelet変換用ライブラリ。コチラのqiitaが詳しい
    mecab ★★ 日本語形態素解析用ライブラリ。自然言語処理をするなら
    gensim トピックモデル、word2vec, doc2vecなどを作るライブラリ

    深いアレたち

    Deeplearning用のやつ。最近乱立してて、キャッチアップし切れていない感もあるけど、気になる奴らをとりあえず拾ってみる

    ライブラリ 用途
    sonnet DeepMind社謹製深層学習ライブラリ。以前記事でも少し取り上げた
    chainer PFN社が作る国産ライブラリ、日本語ドキュメントが豊富
    tensorflow Google謹製OSS。とっつきづらいが圧倒的人口
    edward 確率的プログラミング用のライブラリ。tensorflowのラッパー
    keras thaanoやtensorflowのラッパー、簡単にネットワークを構成できる
    pytorch chainerをフォークして作られたライブラリ。ドキュメントやチュートリアルが充実している
    chainerMN 画像の学習で世界最速を実現した(記事 )並列分散学習パッケージ
    chainerRL 深層強化学習用ライブラリ

    参考記事 : 【PyTorch、Chainer、Keras、TensorFlow】ディープラーニングのフレームワークの利点・欠点【2017年10月更新】 - HELLO CYBERNETICS

    機械学習のお勉強

    論文

    arXiv

    日々更新されるarXivから興味のあるものを拾う。

    https://arxiv.org/list/{}/recent

    このURLの{}部分を変えると、いろんなジャンルの論文が読める。例えば↓

    • stat.ML : 機械学習全般
    • cs.CV : 画像処理系
    • cs.NE : 進化計算系

    尚、最近アーカイブのML系論文をHTML系形式で読めるArxiv Vanityなるものを知った。

    また、オープンソース型の最新論文情報共有サイト、arXivTimesなるものもあり、issueで論文のひとことメモを残していく形になっている。

    またまた、arxivの要旨とgithubソースコードがいっぺんにまとまったGitXivなるものもある。面白そうなものを素早く試せそうで良。

    カンファ

    e-learning

    Andrew Ng先生のMachine Learningチャンネルが勉強にはとても良さそう。

    www.coursera.org

    Deeplearningチャンネルも開設された。

    www.coursera.org

    読んだ本/積読本を載せたい。

    • 難易度とオススメ度は主観(3段階)
    • 統計、機械学習
    • これも随時更新
    難易度 オススメ度 内容 or 感想
    統計学が最強の学問である ★★★ 統計がどういう場面で使われているかわかりやすい一般書。まずイメージをつかむなら
    統計学入門 (基礎統計学?)
    自然科学の統計学 (基礎統計学)
    人文・社会科学の統計学 (基礎統計学)
    ★★ ★★★ 東大の統計の授業でも用いられている教科書。非常に網羅的でよい。数式もきちんと理解したいなら必読。ちなみにコレの後に続くシリーズで、自然科学の統計学人文・社会科学の統計学がある。難しいらしい。
    データ解析のための統計モデリング入門――一般化線形モデル・階層ベイズモデル・MCMC (確率と情報の科学) ★★★ 統計モデリングをコード実行例を含めて非常にわかりやすくまとめている。言語がRなのが(個人的に)玉に瑕だが、良書
    はじめてのパターン認識
    わかりやすいパターン認識
    続・わかりやすいパターン認識―教師なし学習入門―
    ★★★ 通称『はじパタ』機械学習の網羅的な入門だと、これがいいかもしれない。数式もきちんと記述されているので、どういう仕組みで動いているかのイメージが出来る。このシリーズにも続きがあって、『わかパタ』、『続わかパタ』があるが、続わかパタはかなり難しい*1
    深層学習 (機械学習プロフェッショナルシリーズ) ★★ ★★ ディープラーニングの理論的入門書として、網羅的でとてもよい。しかし、2年前の本なのでもう最先端のディープからはすこし違うところもある。けれど何やっているのかを把握するのにはオススメ
    パターン認識と機械学習 上
    パターン認識と機械学習 下 (ベイズ理論による統計的予測)
    ★★★ 通称『PRML』読むなら修行のつもりで。かなり数式が多い。この内容がわかるようになると、特にベイズ周りの扱いにはとても強くなると思われる。なお、副読本もある(パターン認識と機械学習の学習―ベイズ理論に挫折しないための数学)
    ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 ★★★ ディープラーニングでCNNを実際に全部自分で実装しながら学ぶやつ。プログラミングの練習にもなり、またどういうデータが入力になってどう出力されるかも明確にわかるので理解が深まる。
    言語処理のための機械学習入門 (自然言語処理シリーズ) 積読 積読 自然言語の入門書として名高い。読みたい。
    異常検知と変化検知 (機械学習プロフェッショナルシリーズ) ★★ ★★ データ分析案件で結構な頻度出てくる異常検知。統計的な異常検知は割と網羅的。最近はディープラーニングを用いた異常検知もあるが、それは含まれていない
    時系列解析入門 ★★ ★★★ 時系列分析の教科書的存在。それなりに難しいが、それは時系列という存在が難しいのでやむなし。かなりわかりやすく書かれている。
    岩波データサイエンス Vol.6 積読 積読 最近出た時系列解析の本。各論的でレベルも高いが、かなり最先端の技術に触れられる。
    詳解 ディープラーニング ~TensorFlow・Kerasによる時系列データ処理~ 積読 積読 CNNを用いた画像分析はかなりいろいろと出回っているが、時系列データ処理に特化したディープラーニング本ってあまりないと思っている&興味分野なので、読みたい
    深層学習 Deep Learning 積読 積読 有名な本。プロフェッショナルシリーズよりは難しい。実際の研究事例がまとまっているようなものなので、ディープラーニングをもうちょっと深くしたくなったら読む予定。
    代数幾何と学習理論 (知能情報科学シリーズ) 積読 積読 ガチ理論。なぜか学習が起こるのか、とかそういうの(だと思っている)。これと情報幾何は趣味程度に読み進めたい。
    これからの強化学習 ★★★ ★★ 強化学習自体ややこしいので、結構読み進めるのは難しいが、基本が網羅的に学べ、またDeep Q-learning(DQN)についても和書で初めて触れた本。がんばって読み進めると、かなり詳しくなれる。

    まだあった気がするが、、、とりあえずこのくらい。。。

    • 数式に自信ある : 難易度関係なくオススメから
    • 数式はあまり... : 難易度低いの中心に

    自分の興味のある範囲のものを読んでみればいいと思います。

    twitter

    • 興味がある分野での有名な人のtwitterを抑えておいたら、やはり色々と捗る。

    データを集める

    • 最近の機械学習pythonライブラリ(chainer, tensorflow, sklearn, statsmodels, prophet, etc... )はdatasetクラスが用意されていて、予め有名なデータが保存されている。
    • オープンデータなら、とてもいいまとめ資料がこちらにある :
      beginning-ai.hatenablog.jp

    • 政府統計の総合窓口(e-Stat) : 日本人の統計データが色々とある。APIもあるので、データを扱いやすい。

    • 先も紹介したCVPaperに、CV用データセットが載っている
    • Kaggleデータ分析コンペ。上位入賞者は結構な賞金がもらえる。データも面白いものが多かったりする。最近ではメルカリデータとか?データ扱う練習 or 賞金狙い でやってみるのも良し。

    チートシート

    情報が散らばっているので、とりあえず集積してみた。が、あまりにも量が膨大なので、自分が何を勉強したいかを把握しながらすすめていくといいと思った。そこで役に立つのがチートシート

    下記サイトは、チートシートのまとめをしてくれている。結構網羅的。

    becominghuman.ai

    終わりに

    時代によって移り変わりが激しすぎるので、今後も定期的にアップデートしたいなと思う。

    あと、理解するために

    • タスクは何か
    • インプット、アウトプットは何か(実装レベルで)
    • 既存のものに比べてどう嬉しいのか
    • (できれば)なぜそういう恩恵があるのか、理論的考察

    をきちんと抑えながら理解をしていきたいなと思う。

    さて、明日はどうしようかな。

    *1:ノンパラメトリックベイズを扱っている

    『データ分析勉強アドベントカレンダー、全部俺』を、します。

    こんにちは、ほけきよです。

    明日から師走ですね。一年がたつのも早いものです。 ところで皆さんは「アドベントカレンダー」なるものを知っていますか?

    最近ブログをサボり気味だったこともあり、またデータ分析の勉強をしたいなとも思っていて、 一人データ分析ガチ勉強アドベントカレンダーを実施します!

    アドベントカレンダーとは

    アドベントカレンダー(Advent calendar)は、クリスマスまでの期間に日数を数えるために使用されるカレンダーである。アドベントの期間(イエス・キリストの降誕を待ち望む期間)に窓を毎日ひとつずつ開けていくカレンダーである。すべての窓を開け終わるとクリスマスを迎えたことになる。(Wikipediaより)

    もともとは、子供たちに対してクリスマスへの期待感を高めるために使われています。小窓をあけると、お菓子とか小物とかが各窓に入っている用です。なんだかオシャレですね!

    技術者界隈のアドベントカレンダー

    特に技術者界隈のアドベントカレンダーは少し様相が違います。 12/1から12/25までに、各テーマをひとつ掲げ、毎日1記事ずつ、記事をあげていきます。 一人でやるわけではなく、そのテーマに興味を持った人が集まりながら、わいわいとカレンダーを埋めていきます。

    カレンダーを作るプラットフォームの有名どころは二つあって、

    • Qiita HP
    • Adventar HP

    です。Qiitaは技術中心、Adventarはもっと広くいろんなジャンルのカレンダーっていう印象です。

    ほけきよのアドベントカレンダー

    本来わいわい集まりながらカレンダーを作るものですが、今回わたしは一人で実施します...!

    リンクはこちら

    adventar.org

    題の通り、一ヶ月間、復習もかねつつデータ分析のガチ勉強をしていこうと思います。 書きたい内容は以下の通り。

    • データ分析の話全般(論文/記事などを参考に)。特に↓のジャンル
    • pythonライブラリの勉強。ワンランク上の分析技術を身につけるために
      • numpy,pandas,scikit-learnについて総ざらい
      • 機械学習系ライブラリを使ってみる
        • keras, pytorch, prophet, statmodels, ...etc...
    • 実際にデータ分析
      • スクレイピング・クローリング周りの技術
      • ブログのデータを用いて
      • オープンデータを用いて

    上記の何割書けるかわかりませんが、できる限り書こうと思います。間違っているところなどあったら、コメントください。

    また、日によって出来にムラがあるかと思います *1。当日には埋められないことがあるかもしれません。でも、なんとか25日がんばって埋める所存ですので、どうか見てやってください。データ分析をしたことがある駆け出しの人なら、きっと役に立つはずです!

    ネタも募集中

    皆さんから、「データ分析でこんなことを知りたい」とか、「こんな話題を取り上げてほしい」、「このデータ面白そうじゃない?」って言うのも受け付けたいなと思います。オッ、これは、、、と思うものについてはがんばって記事にします。

    最近はやっているSarahah*2で、質問を気軽に受け付けます。 なんでも質問してください!!

    hokekiyoo.sarahah.com

    とりあえず完走する、、、ではではっ!

    ※なお、アドベントカレンダー関連の記事には【AC-#】という通し番号をつけておきます。普通の記事も投稿する予定ですので、データ分析に興味がない人もお楽しみに!

    *1:最終的には出来たものをリライトしてまとめたりもするかもしれないので、その辺もおいおい考えていきます。

    *2:匿名質問箱

    既成概念をぶち壊す!『レアンドロ展』のみどころは?

    こんにちは、ほけきよです。

    皆さんは『レアンドロ・エルリッヒ』をご存知ですか。 レアンドロ・エルリッヒを知らなくても、21世紀美術館なら知っているかもしれません。 21世紀美術館を知らなくても、この画像なら見たことがあるかも知れません。

    服を着ているのにまるで水中にいるかのようなプール。 彼の代表作とも言える作品で開館時時から大人気です。

    そんな気鋭の芸術家、レアンドロ・エルリッヒの展示会が、六本木の森美術館でスタートしました!

    レアンドロ・エルリッヒ展 観ることのリアル

    本展は、エルリッヒの四半世紀にわたる活動の全容を紹介する、世界でも過去最大規模の個展です。新作を含む44点の作品を紹介し、その8割が日本初公開となります。

    • 会期 2017.11.18(土)~ 2018.4.1(日) (会期中無休)
    • 開館時間 10:00~22:00(最終入館 21:30)
      • ※火曜日のみ、17:00まで(最終入館 16:30)
    • 会場 森美術館六本木ヒルズ森タワー53階)
    区分 料金
    一般 1,800円
    学生(高校・大学生) 1,200円
    子供(4歳~中学生) 600円
    シニア(65歳以上) 1,500円

    行ってみた、見所

    既成概念をぶち壊す

    エルリッヒ展の見所は、「リアリティ」のあり方。 エルリッヒの手にかかれば一見当たり前に見える景色に少しの非現実が混ぜ合わされ、不思議な空間が作り出されます。 21世紀美術館でのスイミングプールもそう。「水中では服は着られない」という固定観念を破壊し、新たな価値観を形成する。

    そんな作品がエルリッヒ点ではズラッと並びます。

    水に浮かんでいるかのようなボートの写真。水は反射するものだという既成概念を利用している。

    作品を通してわたしたちは、見るという行為の曖昧さを自覚し、惰性や習慣、既成概念や常識などを取り払い、曇りのない目で物事を「見る」ことで、新しい世界が立ち現われてくることを、身をもって体験することになるでしょう。

    インスタ映え?する鏡の錯覚

    個人的な今回のエルリッヒ展のみどころは、「鏡を使った錯覚」 普段見ている当たり前にみえる風景のはずが、鏡に寄って我々は混乱状態に陥る。

    この展示は一部が本当につながっていて一部が鏡の空間。一度その中に入ってしまうと、どう歩いていけばよいのかわからなくなる。


    (パンフレットより)

    特に今回の目玉作品でもある、"Building" こんな写真がとれます。インスタ映え?しそうじゃない?笑


    (パンフレットより)

    これも鏡を上手に使っていて、実際はこんな感じになっています。

    ネタバレ写真を見る

    一緒に行っていた友人は鏡か現実かわからず鏡に突進していってぶつかっていました。笑 それほど、大きなオトナすら混乱してしまう作品!

    まとめ

    いかがでしたか?参加型の個展、とても楽しく回ることが出来ました。

    友達、カップル、家族等、誰と行っても楽しめる良い展示だと思います。私も年齢を忘れて終始はしゃいでいました!笑

    興味を持った方は是非足を運んでみてください。超絶オススメです!ではではっ!

    大谷や清宮の海外評価は?メジャースカウトのブログ『2080baseball』が面白い!

    こんにちは、ほけきよです。

    今年も野球はアツかったですね!高校野球も、プロ野球も。 高校野球ファンの私ほけきよ。いい選手がプロやメジャーで活躍していくのを見るのが好きです。

    最近は、彼らのプロから見た評価とか、どうやって選手を見つけてるのとか、どこを見て評価しているのか? とかが気になってきてます!最近読んだ"スカウトデイズ"という本は、スカウトが主人公です。なかなか面白いですよ

    スカウト・デイズ (講談社文庫)

    スカウト・デイズ (講談社文庫)

    陰謀や政治渦巻くスカウティング。高校生のころには見たくない本ですが、大人になってから読むと引き込まれてしまう。大人な野球ファンならオススメの小説です。

    と、前置きが長くなりましたが、今回はそんなスカウトのサイト。しかもメジャーリーグ! アメリカのメジャースカウトが才能あふれる若者を評価したサイト『2080baseball』をご紹介します!

    2080baseball

    2080baseballでは、メジャーリーグのスカウトたちが、将来有望な選手の評価を掲載しています。

    • ドラフト全般の記事
    • 有望選手のランキング、詳細レポート
    • 実際に試合を見に行ったときの動画

    など、将来のメジャーリーガーの情報が密に詰まったサイトです。

    大谷など「日本人選手」たちの評価は?

    今年2017年だと大谷翔平メジャーリーグというニュースが大いに話題になりましたね。 これって日本で騒いでいるだけなの??海外のスカウトの反応ってどうなの??
    と思って、このサイトをあさってたんです。

    Scouting Report Library - 2080 Baseball

    すると、大谷はリストアップされた選手の中でもトップのようです*1

    では、もう少し詳しく見てみましょうか。Reportのページを見てみます。

    Shohei Ohtani - 2080 Baseball

    • ローテーションのトップに入る選手
    • 大事なゲームに強いメンタリティ
    • どんなポジションだって対応できる能力

    (多分こういうこといってる。) べた褒めですね。是非活躍してもらいたい!

    清宮や中村奨成など、「スター候補」たちの評価は?

    ホームページ内にこんな記事を見かけました。

    2080baseball.com

    日本プロ野球のドラフト情報、海外でも注目されているようですね。怪物清宮幸太郎や、甲子園のホームラン記録ホルダー中村奨成などのメジャー目線の情報が載せられています

    清宮幸太郎の評価

    • NPBのドラフトで多くの球団が1巡指名したのがうなずける
    • 阿部慎之助に似たスキルセットを持っている
    • 走力と守備力が懸念
    • 伝統的な4番ファーストの左打者

    中村奨成いて

    • 今年のドラフトで最も評価の高い捕手
    • 守備/パワーともに優秀
    • 巨人の坂本勇人に似たフォームや打ち方
    • 坂本のように、プロで筋肉をつけていくことを期待

    なんて書いています! 最近では日本の野球選手も海外の評価が上がっていますからね!今後の成長が楽しみです(´ω`)

    まとめ

    このほかにも、メジャーの今年のスカウト選手ランキングだったり、選手の動画だったりと、とにかく盛りだくさん。今年のスカウトランキング1位の選手は『Kyle Wright』らしいです。いい球!

    www.youtube.com

    スカウティングレポートも含め、「ああ、こんな感じで選手をみているんだな」とわかって面白いです。

    メジャーに興味のある皆さん、また日本の有名選手たちが海外でどのような評価をされているか知りたい方、是非2080baseballをのぞいてみてはいかがでしょう?ではではっ!

    *1:多分Futureというのが将来的なことを踏まえたうえでの評価だと思っています。

    記事生成自動化のススメ

    こんにちは!ほけきよです。

    自分できちんとした(?)文章を書くのは久しぶりです。

    それまで何をしていたかというと自動記事生成のためのプログラム書いたり、泥臭いHTMLの調整したりしていました。 ある程度まとめて仕上げたくてね。それもだいぶ落ち着いてミニサイト風にすることができたと思います。

    今回は、自動生成記事を作ってみての気づきをまとめておこうと思います。

    ウェブ上の自動販売機にしたかった

    もともとのモチベーションは、新鮮で有益な情報を自動で集め、更新する記事をいくつか作ることでした。 フォーカスしたのがセール情報。客観的な情報というのは誰が見てもそうである情報なので、自分の感情を入れる必要がないのです。 そしてそれは機械がもっとも得意とするところでしょう。

    機械でできるところは機械でさせたい! と思い、チャレンジしました。

    そのときの様子などは前に記事にしたので、ご覧ください。

    www.procrasist.com

    テンプレート+自動情報収集のススメ

    時間を割く箇所が変わる

    商品紹介などを多くこなす人などは、構成をテンプレート化している人も多いと思います。 情報を入れる箱を用意しておいて、その箱に情報をはめ込むことで、効率的に記事を作ることができます

    基本的には、テンプレートはあらかじめ用意して、情報の質を上げていく。という方向で記事を書くのではないでしょうか。 しかし、情報が自動収集できるのであれば、その方向性は逆転します。 テンプレートの質向上に時間を費やすことができるのです。

    見せられる情報にするまでの泥臭さ

    ある人がコメントで「こんなの簡単だろwだれでもできるわww」と言っていました。 技術的にはその通りで、そんなに難しいことをしていません。実際1時間もあれば情報を抜き取るスクリプトを組むことはできます。

    けど、 抜き取った情報を人様に見られるようにするためには、また別次元で時間がかかります。しかもとても泥臭い

    できそうと思うひとは一度チャレンジしてみるといいと思います。実はものすごーーーーく細かな、ものすごーーーーく泥臭い作業のオンパレードですよ。 たとえば、
    「カッコ"("が全角の場合と半角の場合がある...」
    とか。もうそういうのばっかり。

    自動情報収集により、UIに全振りできる

    見せ方情報へのアクセスのしやすさなどの、いわゆる定量化しづらい部分は、やっぱりセンスが必要です。けれど、読者にとってはとても大事。 ウェブ力の足りない私、「これなら、まあ見やすいかな」の妥協点に達するまでに、かなりの時間がかかりました。

    逆に言うと、情報を簡単に収集できるようになったからこそ、UIやSEOに意識を全振りさせることが可能になりました。 入れる情報は一緒だからこそ、見せ方や文言を変えるとGoogleや読者はどういう評価をしてくれるのか、その箱の試行錯誤に集中できるようになりました。

    機械にできるところは機械に任せ、人が行わなければならないところだけ注力する。 それができるようになっただけでも、自動化記事導入のメリットがありました。

    Googleのスパム判定...

    一個だけ、注意点というか、実際起こったことなので書き残しておきます。 このKindleセール情報の記事は、多くの読者に読んでいただき、また公開してからの数日、このページからたくさんの商品を購入していただけました。 普段ひと月で10000円いくか行かないかの当ブログ、この記事公開後の三日間だけで10000円分の報酬となりました。ゆきち、とてもうれしい。

    www.procrasist.com

    またブックマークもたくさんいただけました。いい記事になったと自負しています。 公開後の3-4日で、
    Kindle セール」で検索順位が8-12位くらいをうろうろしていました。

    しかし、公開1週間後くらいから、様子がおかしくなります。 いくら探しても、自分の記事が検索に引っかからなくなりました。

    調べてみると、どうやらリンクが多すぎて、文章量が少なすぎると、Googleが自動的にスパム判定をするらしい。 (参考 : Googleペナルティの原因と確認・解除方法)

    見やすさを重視して文章をなるべく削ぎに削いだ結果がスパム判定。残念すぎる。 2週間くらい我慢してみても戻ることはありませんでした。

    結局、本来別記事に分けるはずだったKindleについてのQ&Aをむりやりページ後部につけることで、文章を水増し。 すると、検索順位が翌日から12-20位くらいまで戻りました。なんか前時代的なナニカと自分の欲望に負けた感があって悔しいけれど、まだGooglebot自体はUI等をきちんと評価できるものではないのでしょう。人によって違いますしね。

    検索順位監視中

    現在Amazon関連のミニサイトをつくり、いろいろと順位を監視したりしています。 Amazon セール hogeのワードで1ページ目に載せられればいいのですが、まだ2ページ目が多いですね。 公開1ヶ月ということも関係あるのかもしれませんが、内部リンクや、際と設計、ワーディングなども関係しているのでしょう。

    今後Amazon関係のサイトに関しては、上位取れるよう、勉強しながら試行錯誤していきたいと思ってます!内容は自動収集の分、そういうところに注力できるのがありがたい!

    使った技術

    「どのようなことを勉強すればこういうことができるようになるの?」

    という意見をいただいたので、本当に簡単に、使った技術に関して「こういうワードをググればいいよ」程度の列挙を。わからなければ聞いてください。

    • スクレイピング/クローリング : Web上の情報収集テクニック
    • Amazon API : Amazonが提供する、スクレイピングを簡単に行えるAPI
    • Python : 上記を実現するための言語。別に何でもよいが、周りに聞ける言語がいい。
    • HTML/CSS : 記事の体裁を整えるために知っておくといい。外注してもいいと思う。お金があったら外注したい。
    • Bootstrap : 記事のスタイルを簡単に調整できる。ちょっと読み込みおそくなるのかな?最近バージョンアップ(bootstrap4)したが、3系の記事が多いので注意。

    まとめ

    いかがでしたか。機械ができる部分と人間がしなければならない部分を明確に切り分けることによって、 本来すべき作業にだけ注力できる。これがもっとも大きなメリットですね。 あと副次的な効果として、HTMLやCSSに対するアレルギーが消えましたはてな記法みたいにプラットフォーム依存の言語を書くくらいなら、HTML直書きのほうが、ちょっと学習コスト高いけどあとあと楽かなと思いました。

    あ、これルーティンワークじゃね?と思ったら自動化のチャンス!機械にやらせちゃいましょう!ではではっ

    PROCRASIST