notebook 001

notebook 001

INPUTとOUTPUTの個人的な備忘録です。

線形回帰をstatsmodelsで実行・2回目(簡略な書き方編)

statsmodelsとscikit-learn

Python機械学習といえばscikit-learn。ですが、まずは統計学寄りのstatsmodelから触ってみる。statsmodelは予測モデルの表示に加えて、その名の通り、統計的な情報、例えば検定結果も計算して表示する。t値とかp値とか。

Webの情報を探すのに疲れてきたので、Python本を購入。 そしたら、前回の内容よりも、短く書けるやり方が分かったので、書き直した。「切片が必要だったら書くべし」という、前回のおまじないのような一文も不要。

 

前回の内容

mkmkipy.hatenablog.com

 

購入した本

まとまってて効率的!早く買えば良かった。

Pythonで理解する統計解析の基礎 (PYTHON×MATH SERIES)

Pythonで理解する統計解析の基礎 (PYTHON×MATH SERIES)

 

 

線形回帰とは

線形(直線)に回帰する。

y=b1x1+b2x2+b3x3+...+bnxn+b

  • x1, x2, x3, ... xnは、説明変数
  • yは、目的変数(説明変数を使って目的変数を予測する)
  • b1, b2, b3, .... bn は、係数
  • bはy切片

説明変数が1つだけの場合は「単回帰分析」、2つ以上ある場合は「重回帰分析」と呼ぶ。例えば、

  • 「気温」から「かき氷の売上」を予測するモデルを作成するなら、単回帰
  • 「気温」「風量」「降水量」から「かき氷の売上」なら、重回帰
  • 「気温」「風量」「降水量」「天気」から「かき氷の売上」なら、重回帰

最後の例は、回帰に数値データだけではなく「天気」のような離散値(カテゴリ変数)を、説明変数として持つ場合の回帰である。

線形回帰をやってみる

Pythonコード全文は最後に掲載。ポイントのみ記載。

使用するデータ

ワインの品質(赤ワイン)のデータセットを使用する。

UCI Machine Learning Repository: Wine Quality Data Set

データはこんな感じ(先頭5行を表示)。

f:id:mkmkipy:20181013035937j:plain

quality列が品質を示す。定義より、qualityは0~10。
しかし、実際の値とそれぞれの件数は 、print(df['quality'].value_counts()) より

5 681
6 638
7 199
4 53
8 18
3 10

つまり、quality列の値は、3, 4, 5, 6, 7, 8 の6種類である。

単回帰分析

「dencity(濃度)から、alcohol(アルコール度数)を予測する」とする。

import pandas as pd
import statsmodels.formula.api as smf

# UCI Machine Leaning Repository 「Wine Quality Data Set (ワインの品質)」の赤ワインのデータセット
df = pd.read_csv("http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", sep=";")

### 単回帰
### dencity(濃度)から、alcohol(アルコール度数)を予測する
formula = 'alcohol ~ density'
result = smf.ols(formula, df).fit()
result.summary()

おっと。説明変数と目的変数を使っていきなりfomula='Y ~ x1'で書けばあとはfit()すればいいのね。smf.ols() 指定によって、データに対して、残差二乗和(Ordinary Least Seuares)が最も小さくなるような回帰直線を求めることを指定している。

実行結果

f:id:mkmkipy:20181027225516j:plain

結果の確認

参考文献にある単回帰分析の例にある回帰式の係数と切片が、今回の例と同じことを確認した。(実行結果内の、Intercept(切片)とdensity説明変数の、Coef(coefficient, 係数)の値)

[alcohol] = -280.16382307 × [density] + 289.675343383

実測値データ(青)と回帰直線(オレンジ)をプロットした図。

f:id:mkmkipy:20181027170155p:plain

重回帰分析

 説明変数が2つ以上あるものを重回帰分析と呼ぶ。ここでは「quality」を目的変数に、「chlorides」「density」「pH」「sulphates」「alcohol」を説明変数として、重回帰分析を行う。書き方は単回帰の場合と同じで、fomula='Y ~ x1 + x2 + x3+ ...' で、説明変数を複数個、+で繋いで指定する。

 

formula = 'quality ~ + chlorides + density + pH + sulphates + alcohol'
result = smf.ols(formula, df).fit()
result.summary()
実行結果

f:id:mkmkipy:20181027225534j:plain

補足(未解決:変数にスペースを含む場合)

当初、説明変数にquaility列以外の列を全て使おうと次のように指定した。ところが、変数名にスペースを含むとSyntax Errorで失敗する。

formula = 'quality ~ fixed acidity + volatile acidity + citric acid + residual sugar + chlorides + free sulfur dioxide + total sulfur dioxide + density + pH + sulphates + alcohol'

 

Traceback (most recent call last):

  File "C:\Users\xxx\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 2963, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
...(略)...
  File "C:\Users\xxx\Anaconda3\lib\ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)

  File "<unknown>", line 1
    free sulfur dioxide
              ^
SyntaxError: invalid sy SyntaxError ntax

 

なので、スペースを含まない変数だけを目的変数に指定した。(誰か知ってたら教えてください...)

 

重回帰分析(説明変数にカテゴリ変数を含む)

ここまで扱ってきたデータは、数値データ(連続値)のみである。ただ実世界で扱うデータには、「男性・女性」「赤・青・黃」「月曜・火曜・・・日曜」のような、非連続な値を取るデータが存在し、これをカテゴリ変数と呼ぶ。

ワインのデータでは、「quality」列は先頭で確認したように、3, 4, 5, 6, 7, 8 の6種類であるが、これは最高級、高級、並、、、のような分け方でも構わない。見た目は数値だが意味的にはカテゴリ型と見なしてもよいだろう。

では、「density」と「quality(カテゴリ変数とする)」を説明変数として、「alcohol」を予測する。カテゴリ変数を含む線形回帰も先の例と書き方は同じで、fomula='Y ~ x1 + x2' で指定。でも、実行結果に注目。

 

formula = 'alcohol ~ density + quality'

 

実行結果

f:id:mkmkipy:20181027223817j:plain

カテゴリ変数を回帰式に導入するには、ダミー変数に変換する必要がある。コード内では特に指定していないが、自動的に変換されている。
quality列は3, 4, 5, 6, 7, 8 の6種類あるので、quality[T.4]からquality[T.8]の全部で5つ(値の種類 -1)の、ダミー変数が導入されていることが分かる。え?3はどこへ?

  • quality=4の場合、ダミー変数のquality[T.4]=1, 残りは0
  • quality=8の場合、ダミー変数のquality[T.8]=1, 残りは0
  • quality=3の場合、ダミー変数は全て0

と表現される。なので、ダミー変数の個数は、カテゴリ変数の値の種類から一つ少なくなる。

y=b1*<density> + b2*<qualityが4の場合> + b3*<qualityが5の場合> ... +b4*<qualityが8の場合>+切片

 

補足(カテゴリ変数であることの指定)

カテゴリ変数に含まれる値が文字列であれば、自動的に離散値だと見なし、カテゴリ変数扱いしてくれるが、quality列は数字だ。なので、今回はCSVファイル読み込み時に明示的にString型であることを指定した。


df = pd.read_csv("winequality-red.csv", sep=";", dtype={"quality": str})

 

おまけ(printf()は必要か?)

Jupyter Notebookで実行してるが、result.summary()と書いて結果が表示されたりされなかったり。表示されない場合は、printf(result.summary())を書いていたが解決した。

Jupyter Notebookの各セルの一番最後にある実行は、自動的に表示される。

なので、セルの最終行がresult.summary()になるように書けば不要。

そしてなぜか、printf()を付けたときはベタなテキスト書きだが、付けない場合は表示がきれい。

ソースコード全文

 

今日の単語帳

  • 線形回帰:Linear Regression
  • 単回帰分析:simple linear regression analysis
  • 重回帰分析:multi regression analysis
  • 説明変数:explanatory variable 
  • 目的変数:objective variable 
  • 切片:intercept
  • 係数:coefficient

 

 

Pythonで理解する統計解析の基礎 (PYTHON×MATH SERIES)

Pythonで理解する統計解析の基礎 (PYTHON×MATH SERIES)