統計と機械学習

Pythonで数量化1類

統計と機械学習

[PR]当サイトはアフィリエイト広告を利用しています。

そろそろパソコンを新調したいというときはこちらもどうぞ。安さと機能のバランスが取れたPCを紹介しています。

プログラミングおすすめPC

マウスコンピューターのセールもチェックすると掘り出し物が見つかるかも。

※2021/01/22に公開した記事ですが、導入部やダミー変数などの説明をよりわかりやすくするために、少し追記しました。その他文章のこまごまとした言い回しなども修正して、2022/10/06に再度公開しました。

今回は統計分野の数量化1類を勉強したので記録を残します。

統計は素人なので、間違いもあるかもしれません。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

それでは解説。

今回は作物の高さと肥料、日照条件からどの要素の影響が大きいかという分析をしてみます。

手元にデータがないので、仮想的に考えた結果を使います。実験の結果こんな結果になったらこういう分析ができるという仮のお話です。

仮想的なデータは以下。

化成なし化成あり液肥なし液肥2週に一回液肥週1日照短い日照長い作物高さ
011001051
011001052
100101050
100101051
100011051
100011049
011000160
011000161
100100161
100100162
100010160
100010161

このデータを基にscikit-learnとpandasで重回帰分析を行います。

※今回は重回帰分析ですが、SVR(サポートベクトル回帰)で回帰した記事もあります。よろしければそちらもどうぞ。

最終的に何がしたいのかわからないと、読んでいてもさっぱりだと思うので、初めに結果を示します。

最終的な結果は、作物高さが

作物高さ=0×液肥2週に1回 + -0.75×液肥週1回 + 10.1667×日照長い+50.92

という式で表せる。

これをやりたいのです。

日照長いの係数がおよそ10。

他の係数は0と-0.75。

つまり「日照の影響が作物高さに大きく影響している」。

こういう結果を導きたいのです。

ちなみに「液肥2週に1回」は0か1の変数となります(この記事の途中に記述した「ダミー変数」をご覧ください。)。

まずじーっとこの表を見ます。

そもそもの前提としてこの表は、化成あり・なしの列は「化成肥料」の二つのカテゴリーを、液肥なし・2週に1回・週1は「液肥」の3つのカテゴリーを、日照短い・長いは「日照」の2つのカテゴリーをダミー変数でありなら1、なしなら0と変換したものです。

ちなみにダミー変数というのは、文字列変数を数値で扱うための変数のことです。

例えば、どこかに「行った」というのは、「行った」という変数は作れませんが、「行った」か「行かなかった」かのYes、Noの二択にすれば、Yesを1、Noを0とすることで、数値で扱うことができます。

この0と1が「ダミー変数」と呼ばれています。

scilit-learnでは変数を数値で扱うので、こうしたダミー変数という手法を用います。

今回は肥料を与えた頻度(2週に1回)などの「ある」「なし」をダミー変数にしています。

これは数量化1類と呼ばれていて、参考とした文献は以下。詳細は割愛します。

涌井良幸、涌井貞美(2020)『ファーストブック 多変量解析がわかる』技術評論社.

さらに表をじーっと見ます。

すると「化成なし」と「化成あり」のデータを横に足すと、必ず1になることを発見します。

このようなデータは多重共線性と呼ばれている現象が発生しており、このような列は一方を表から除外する必要があります。この場合は「化成なし」を除外します。

多重共線性については以下の書籍を参考として挙げます。

川端一光・岩間徳兼・鈴木雅之(2020)『Rによる多変量解析入門 データ分析の実践と理論』オーム社.

これは一方が決まれば他方が決まるという話であり、除外したほうは、除外しない方で0を入力した場合ですべて説明できるため、なくても良いのです。

これと同じ現象が、「液肥なし」と「液肥2週に1」・「液肥週1」の3変数間と「液肥なし」と「化成あり」、「日照短い」と「日照長い」にも発生しています。

よって、「液肥なし」と「化成あり」と「日照短い」も除外します。

その結果できるのが以下の表です。

液肥2週に一回液肥週1日照長い作物高さ
00051
00052
10050
10051
01051
01049
00160
00161
10161
10162
01160
01161

この表で初めの表の項目がすべて説明できていることを確認します。

例えば液肥2週に1と液肥週1がともに0なら液肥なしと言え、それなら化成ありが1、それなら化成なしは0であるとみなせますよね。

今回は化成肥料を使わなければ必ず液肥を使っているという関係がデータにあるのでこういう除外の方法が使えますが、化成肥料も液肥もなしというデータが存在する場合多重共線性の問題とならずに除外する列は変化します。それについてはそのうち記事にする予定です。

以上で読み込ませる表のデータは完成したので、これをそのままCSVデータ(input2.csv)に出力してPythonのプログラムに読み込ませます。

参考にしたサイトは以下の2つ。

数量化理論をPythonで理解する

【Python/Scikit-learn】数量化1類を実装(説明変数が定量データ)

作成したプログラムは以下。

ちなみにプログラムで分析者がすることはその問題に対するCSVの準備だけで、あとはこのコードにそのCSVを投げれば結果が出ると思います。

pandas v1.2.0
Copyright (c) 2008-2021 the pandas development team.
Released under the BSD 3-Clause License

Package overview — pandas 2.2.3 documentation
scikit-learn v0.24.0 Copyright (c) 2007 - 2020 scikit-learn developers. Released under the BSD 3-Clause License
scikit-learn/COPYING at main · scikit-learn/scikit-learn
scikit-learn: machine learning in Python. Contribute to scikit-learn/scikit-learn development by creating an account on ...
import pandas as pd from sklearn import linear_model df = pd.read_csv("input2.csv") print(df) x = df.iloc[:, :-1] y = df.iloc[:, -1] calcf = linear_model.LinearRegression() calcf.fit(x, y) a = calcf.coef_ b = calcf.intercept_ print("説明変数:", x) print("回帰係数:", a) print("切片:", b) print("決定係数:", calcf.score(x, y))

pandasとscikit-learnはpipなどでインストールしておく必要があります。

13行目でcsvの読み取りをしています。エクセルから出力したcsvなら

df = pd.read_csv(“input2.csv” , encoding=”shift-jis”)

とします。

基本的にエクセルが吐き出したcsvをメモ帳で開き直してUTF-8で保存すれば引数の指定はいりません。

ちなみにエクセルの表をcsvに出力するときは、「名前を付けて保存」の「ファイルの種類」で「CSV UTF-8(コンマ区切り)」あるいは「CSV UTF-8(コンマ区切り)」で保存してください。前者のほうが余計な手間がなくていいですね。古いエクセルのバージョンでは前者がない可能性があります。

コードに関しては

15行目と16行目で変数セルと目的セルを区別します。

15行目で最終列以外のセルをxに格納。

16行目で最終列のセルをyに格納しています。

17行目でインスタンスを作って、18行目で重回帰分析をしています。

19行目で回帰係数をaに格納し、20行目で切片をbに格納しています。

出力は以下。

液肥2週に一回 液肥週1 日照長い 作物高さ

0 0 0 0 51

1 0 0 0 52

2 1 0 0 50

3 1 0 0 51

4 0 1 0 51

5 0 1 0 49

6 0 0 1 60

7 0 0 1 61

8 1 0 1 61

9 1 0 1 62

10 0 1 1 60

11 0 1 1 61

説明変数: 液肥2週に一回 液肥週1 日照長い

0 0 0 0

1 0 0 0

2 1 0 0

3 1 0 0

4 0 1 0

5 0 1 0

6 0 0 1

7 0 0 1

8 1 0 1

9 1 0 1

10 0 1 1

11 0 1 1

回帰係数: [ 1.39523656e-16 -7.50000000e-01 1.01666667e+01]

切片: 50.916666666666664

決定係数: 0.9790521078816444

回帰係数は液肥2週に1回がほぼ0、液肥週1が-0.75、日照長いが約10.1667と出ました。

つまり

作物高さ=0×液肥2週に1回 + -0.75×液肥週1回 + 10.1667×日照長い+50.92

ということです。

今回は初期データを作物の高さが日照に大きく影響を受けるように意図的にデータを作成しました。

そのため日照に関する係数が大きくなっています。

係数の大きさを比較することで元の変数のくくりの影響が大きいかどうかがわかります。

今回は「日照」の影響が大きく、「液肥」の影響が小さいと出ました。

比較のやり方は、変数のくくりの係数の最大値-最小値の絶対値を求めればよいです。

ただし多重共線性のために削除した列を復活させてその係数を0とした状態で比較してください。

例えば液肥なしを0、液肥2週に1回を0、液肥週1を-0.75として0-(-0.75)を計算します。

もし今回と異なるデータを用いて液肥2週に1回が-0.2、液肥週1が-0.75というような係数になったら、液肥なしを0として0-(-0.75)を計算します。

参考:

iStat, Inc. “多変量解析の手法別解説“. https://istat.co.jp/ta_commentary/method1_02, (参照2022-10-06)

また液肥2週に1回の係数が0ということは、液肥週1回が0なら液肥なしを現したことになり、液肥2週に1回がなしと液肥なし、すなわち化成ありが同じ影響度という話になります。

実際に作物を育ててみて元のデータのような結果になるか検証したいところです。

実際は作物を表にあるような条件で育ててみて、実際の高さを求めてみないとわかりません。

実際に育ててみたらまた記事にするかもしれません。

以上数量化1類の備忘録でした。