線形回帰をstatsmodelsで実行・2回目(簡略な書き方編)
statsmodelsとscikit-learn
Pythonで機械学習といえばscikit-learn。ですが、まずは統計学寄りのstatsmodelから触ってみる。statsmodelは予測モデルの表示に加えて、その名の通り、統計的な情報、例えば検定結果も計算して表示する。t値とかp値とか。
Webの情報を探すのに疲れてきたので、Python本を購入。 そしたら、前回の内容よりも、短く書けるやり方が分かったので、書き直した。「切片が必要だったら書くべし」という、前回のおまじないのような一文も不要。
前回の内容
購入した本
まとまってて効率的!早く買えば良かった。
Pythonで理解する統計解析の基礎 (PYTHON×MATH SERIES)
- 作者: 谷合廣紀,辻真吾
- 出版社/メーカー: 技術評論社
- 発売日: 2018/09/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
線形回帰とは
線形(直線)に回帰する。
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行を表示)。
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)が最も小さくなるような回帰直線を求めることを指定している。
実行結果
結果の確認
参考文献にある単回帰分析の例にある回帰式の係数と切片が、今回の例と同じことを確認した。(実行結果内の、Intercept(切片)とdensity説明変数の、Coef(coefficient, 係数)の値)
[alcohol] = -280.16382307 × [density] + 289.675343383
実測値データ(青)と回帰直線(オレンジ)をプロットした図。
重回帰分析
説明変数が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()
実行結果
補足(未解決:変数にスペースを含む場合)
当初、説明変数に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'
実行結果
カテゴリ変数を回帰式に導入するには、ダミー変数に変換する必要がある。コード内では特に指定していないが、自動的に変換されている。
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