名義特徴量と順序特徴量の話

毎日学ぶことがあるので昨日の宿題を日記に残しておく暇がなかった。相関と回帰の違い、分散と共分散の違いはなんとなく理解できたぞということだけメモしておいて、今日は「sklearnでロジスティック回帰分析をする際にカテゴリ型を数値型データに置き換える(ダミー変数にする)」ことについて書くことにする。長い。今回も例によって別の先輩とぎゃーすかやりながら勉強しました。


ロジスティック回帰分析

ってそもそも何よということから。

簡単に言うと、ある物事が「起こるか」「起こらないか」について、他の要因から推測する分析方法。例えば「今日はアイスが売れるか・売れないか」について推測するために、これまで売れた日・売れなかった日のデータ(「その日の気温」「その日の天気」「その日通りがかった人数」など)から予測を立てる方法である。


カテゴリ型を変換する理由

上のような分析をするにあたって、データの持ち方について考える必要がある。いわゆる「データ型」、数値型とか文字列型とかいうものである。

今回特に目をつけたいのは、アイス屋の例えを引き継ぐのであれば「晴れ」「曇り」「雨」のようにデータの入っている「天気」カラムだとか、「成人」「未成年」のようなデータの入った(あるいは年齢だけが入った)「店員の年齢」カラムだとか。機械は数字でしかものの価値を判断できないので、これらのデータは(0,1)の二値か、(0,1,2,3…)のような間接的にカテゴリを示す数値に置き換える必要がある。


順序特徴量と名義特徴量

しかし注意点として、それらのカテゴリの間に優劣があるか、といった問題がある。

たとえば、その日売っていたアイスの種類。全てのアイスが同じ味、しかし日ごとにS,M,Lサイズのどれかしか売らないアイス屋があったとしたら(ないだろうが……)、そのサイズには価値の優劣があるとはっきり考えられる。値段がサイズによって変わるとすれば、Sは安く、売れやすくなるだろうし、Lは高く、売れにくくなるだろう。この場合はデータに与える数値に価値の重みをつける必要がある。こうした「優劣を持つ」カテゴリのデータを「順序特徴量」という。

一方で、その日の看板の色が何色だったか、というような、価値に優劣のない(と考えられる)カテゴリのデータは、単純に(0,1)の二値で表してしまって構わない。「黄色」「赤」「青」三種類だとすれば、それぞれに(0,1), (0,1), (0,1)の判定を行っていく。結果、どれかひとつだけに1がつくことになるだろう。こういったカテゴリのデータを「名義特徴量」という。


それぞれへの対応

実際にどうしていくかという話。処理をする順番としては、「順序特徴量のダミー変数化」→「名義特徴量のダミー変数化」の順に行うのが良い。理由は後述。

順序特徴量のダミー変数化は、マッピングと呼ばれる手法で、手動で行う必要がある。

ice_mapping = {’S’: 3, ‘M’: 2, ‘L’:1}
df[‘ice_size’] = df[‘ice_size’].map(ice_mapping)

こんな感じ。この例では、S,M,Lに辞書型で数値のvalue(価値)を与え、データフレームにそれを投影している。

名義特徴量についてはpandasを使って自動的に行ってもらう。

df_dammies = pd.get_dummies(df)

こんな。get_dummies()は賢いので、数値型になっているものは素通りしてくれるが、そうでないものは一気にダミー変数に置き換える。順序特徴量のダミー変数化(手動の価値付け)より後に行ったほうが良いのはこのため。細かいところは人力で、あとは機械任せ、という感じ。

 

機械学習、少しづつ理解できてきている自覚がある。明日も一日がんばるぞい(眠いので見出しの設定は明日やります)。

機械学習のためのPythonのための統計学の勉強をした

統計学の勉強経歴

なし。 平均はわかるけど偏差ってなんなんですレベル。

勉強をした理由

研修担当の先輩が「(分析について)調べた時に「分散」とかわからなかったらちょっと困ると思いますね〜」といった旨のことをつぶやいていたので。統計学歴/zeroな自分は当然わからないままで一年近くおしごとしていたわけだけれど、困ったことがなかった(ことが困ったことなのでは……と思った)ため。

今日の学習内容

勉強といっても適当に用語を調べただけです(予防線)。

分散

データのばらつき度合い。「各データの、平均からの距離」の二乗の合計を「データ数」で割ったもの。二乗をするのは平均にプラスで離れている場合とマイナスで離れている場合とがあるため。この平方根を取ったものが「標準偏差」。つまり標準偏差の二乗が分散。これをさらにあれこれいじって、どれだけ変数の軸が増えても対応可能にした(最大を1にした)「相関の強さ」が相関係数とのこと。

正規分布

山形(つりがね型?)を描くグラフ。自然に発生する事象であればすべて、発生確率はこれに従う(らしい)。x軸のとある一点が起こりうる確率=中心からその一点までの距離を底辺、正規分布グラフを天井とした面積である。この分布を見れば、「その物事がどれぐらいの確率で起こるのか」を計算できる。

余談。「ある囚人が自分に与えられるパンの大きさのばらつきを記録し、それが正規分布に従っていないことに気づいた。それをもとに、見張りが料理人に賄賂を渡して、大きいパンの場合は自分で受け取って(小さなパンとすり替えて)いたことを突き止めた」という寓話を先輩に聞いた。

ダミー変数

統計学というより機械学習の際に分からなかった単語。「成人:未成年」「曜日」のような、数値で表せない要因(変数)を数値に置き換えたもの。基本的に1か0かの値をとる。文字列型をカテゴリ型に置き換えているということ?

標準化

機械学習の際に分からなかった単語②。「(その状況での)普通」がどこにあるかを設定するために行なっている。例えば10,15,20,18…のような数値の中における50は大きな値だけれども、98,79,100,99…のような数値の中における50は小さな値である。50,50,45,50…の中の50は珍しくないけれども、20,99,12,78…の中の50は珍しい値といえる。そのため標準化して、どこが平均かつ頻繁に登場する値なのかを揃える必要がある。

回帰係数

機械学習の際に分からなかった単語③。そもそも回帰とは「ある説明変数(従属変数)が目的変数(被従属変数)に比例している」という状態を示しているものであり、回帰係数とはその影響度合いを示すものである。線形回帰であれば y = b1x1 + b2x2 + b3x3 + … bkxk の形の式で表せるが、このときxkをそれぞれ説明変数とすると、bkが回帰係数にあたる。これが「絶対値において」大きい数値であるほど、目的変数yに大きく影響を与えている、ということ(逆にマイナスの値を取っても、その絶対値が大きければ大きな負の影響を与えているといえる)。影響が最も小さいのは0=全く影響を与えていない場合。

今回稼働時間の学びはここまで。「相関と回帰って何が違うのよ!」「分散と共分散の違いもわからないわよ! 説明しなさいよ!」という話になって、これも先輩とぎゃーぎゃーやったけど、稼働時間外なので(あと明日のネタがなくなりそうなので)また今度。

jupyterでmatplotlibのグラフ化に躓いた

scikit-learn(サイキットラーン)とは

Python機械学習をするために必要なライブラリ。配列型(データフレーム型?)を使用することが可能になるPandas(パンダス)、計算に強いNumpy(ナンパイ)と組み合わせて使用する。後者二つはimport Pandas, import Numpyの形でインポートするけれども、scikit-learnはfrom sklearn import treeのような形でインポートして使用する模様。

先週からはこのscikit-learnを使ってK-meansクラスタリングをしたり、CART法での決定木分析をしたり、単回帰分析をしたり、ということを試みてきた。「Pythonでデータサイエンス」様(https://pythondatascience.plavox.info/)の説明を拝読しつつ、そちらに掲載されているようなscikit-learn付属のデータを、自力で用意したcsvに置き換えて挑戦している(といって実行環境はJupyterなので、csvをアップロードして読み込むだけの違いではあるが)。

上記三つ、手法や目的こそ違っても基本的な流れは同じで、①ライブラリとデータのインポート②説明変数と目的変数を指定して実行③結果をmatplotlibで可視化 の手順で行われている。個々の話は気が向いたときに追々していくとして、③の段階でずっとグラフが出ずに頭を抱えていたという話だけにとどめておきたい。

matplotlibのグラフが出力されなかった話

結論から言って、%matplotlib inlineで解決した。

matplotlib、前項で上げたような機械学習の結果をグラフに示して表示してくれるものなのだけれども、それがテキストだけを吐き出してうんともすんとも言ってくれずに困り果てていた。エラーというわけではないようでエラー文も出ず、調査のための目途も立たず、弊社の先輩に泣きついたところ、「魔法の言葉を書かなきゃいけないんですよ~」と言われて渡されたのがこれだった。

from matplotlib import pyplot
%matplotlib inline

形としてはこんな感じ。魔法の言葉とだけ言われているので、なぜこれだけで動くのかはっきりしていないのだけれども、とりあえずこれで解決したよということで……。

何かを解決するたびに新たな疑問が出てくるので一向に先に進んでいる気がしない。目標はSPSS modelerを使わずにPython機械学習がある程度できるようになること、なので、丁寧に疑問を摘んでいければと思う。

匿名であるということ

諸々の理由から技術ブログを始めるにあたって、先達に倣うべくはてブロをあれこれ眺めてみたときに、まず感じたことが匿名性の高さだった。

匿名性、というと変に分かりにくいけれども、要するに名前を明かして、あるいはなんらかの名前を表に出して、一個人としてブログを書いている方々が、思いのほかに少なかったということだ(もちろん名前や顔を明かしている方もいるので、自分が触れたものに限ったことだったのかもしれない)(こうした添え書きは正直面倒くさい)。

自分が「特定の肩書き」「固定の名前」を持つ一個人としてネットにいた経験があり、現在も周囲がそうした「名前」の持ち主ばかりの環境に交じっているため、なんとなく「ブログは主体ある何者かが書くものなのだ」と思い込んでいた節がある。ブログは一方通行のもので、どうしても上から下へ与えられるだけのもののように思っていた。だから誰もが敬語で、「誰かに見られている」「誰かに聞かせている」口調で日記を書くのだと。そこに少し疲れていた部分もある。そうではなかった、とわかったいま、少し安心して日記が書けるような気がする。

こんな感じでエモい話もまじえつつ日記を書いていきます。

自分について

といって、何のタグ付けもないことには日記なんて書きようもないので、身バレのない範囲で自己紹介を。

今年からビッグデータ分析系の会社に入社した一年目社会人で、これまで業務経験がある言語はSQLのみ。職場環境の影響と、自分自身ほかに言語ができるようになりたい、ということでPython3の勉強を一か月前に始めたところ。研修でかじったレベルの言語としてはjavaUNIX(ほとんど忘れている)、それから趣味として独学のHTMLとcssを五年ほど。

休みの日はもっぱらソシャゲをしたりsteamで買ったゲームをしたり……つまりゲームばかりしている。Stardew Valleyが大変おすすめなので全人類に遊んでほしい。ニンテンドースイッチでも配信開始されたので。時間が飲まれて生産性ががくっと下がってもいい人だけ。ぜひ。

store.steampowered.com

今年の個人的な目標は「課金は一ヶ月一万円まで」。貯金していこう。

ズンドコ問題

少しは技術ブログらしいこともしておきたいので、先日書いたコードを添えておく。今回はズンドコ問題に挑戦した(詳しくは下のリンクから)。

qiita.com

簡単に説明すると、「ズン」と「ドコ」をランダムに出力しつつ、「ズン ズン ズン ズン ドコ」の並びができたら「キ・ヨ・シ!」を出力して処理終了、とするコードがお題。一時間くらいjupyterとにらめっこして、こんな形で落ち着いた。

import random

zundoko = ['ズン', 'ドコ']
zundoko_list = []
break_flg, i = 0,0
while break_flg == 0:
    zundoko_list.append(random.choice(zundoko))
    print(zundoko_list[i] + ' ', end ='')
    i += 1
    if i >= 5:
        # リストのスライス。返ってくる値は必ず「リスト型」になる
        if zundoko_list[-5:] == ['ズン', 'ズン', 'ズン', 'ズン', 'ドコ']:
            print('「キ・ヨ・シ!」')
            break_flg = 1
         # 無限ループ防止
        elif i >= 100:
            print('ズンドコ失敗!')
            break_flg = 1

もうちょっと効率のいい方法があるんじゃないかなーという心残りはありつつ、「動く」ものはできたので一息ついた。今後もう少しブラッシュアップできたらいいと思う。