1.単回帰分析

  • 単回帰分析とは、2つのデータ群を「原因」と「結果」でとらえたときに、その関係を「回帰直線」であらわすことのできる分析手法
  • 単回帰式 y = ax + b を求めることで、値を予測できる
項目 内容
説明変数(x) 原因系のデータ
目的変数(y) 結果系のデータ
回帰係数(a) 最小二乗法による傾き
切片(b) 最小二乗法によるy切片
決定係数回帰式の精度判断基準として一般的に「単相関係数」を二乗した値が使われる。(決定係数、寄与率などと呼ばれる)0 から 1の値をとり、1に近いほど回帰式の精度がよい(xとyの関係が強い)

2.試してみる

Python 数学、統計、機械学習:散布図と相関分析(1) で描いた散布図に回帰直線を重ねる

scikit-learn に含まれる、線形回帰モデルを利用する。


from sklearn import datasets
from sklearn import linear_model
import pandas as pd
import matplotlib.pyplot as plt
import math


def liner_regression(*feature_index):
    """
    https://pythondatascience.plavox.info/scikit-learn/%E7%B7%9A%E5%BD%A2%E5%9B%9E%E5%B8%B0
    :return:
    """

    # 線形回帰予測クラス
    lr = linear_model.LinearRegression()

    boston = datasets.load_boston()

    df_ex = pd.DataFrame(boston.data)
    df_ex.columns = boston.feature_names
    import pprint
    print(pprint.pprint(df_ex))

    df_res = pd.DataFrame(boston.target)
    df_res.columns = ['Price']

    y = df_res['Price']
    fig = plt.figure()

    cnt = len(feature_index)
    cols = 1 if cnt == 1 else (2 if cnt < 6 else 4)
    rows = math.ceil(cnt / cols)
    idx = 1
    for feature in feature_index:

        x = df_ex[feature]
        ax = fig.add_subplot(rows, cols, idx)

        ax.set_title(feature, fontdict={'fontsize': 10}, pad=2)
        ax.scatter(x, y, s=0.5)

        mat_x = x.reshape((-1, 1))
        mat_y = y.reshape((-1, 1))

        # 予測モデルを作成
        # y = ax + b
        lr.fit(mat_x, mat_y)

        # a:回帰係数
        a = lr.coef_

        # b:切片 (誤差)
        b = lr.intercept_

        # R^2:決定係数
        r2 = lr.score(mat_x, mat_y)

        # 予測を実行
        predict = lr.predict(mat_x)

        # 予測をプロット
        ax.plot(x, predict, 'k--', lw=0.5)

        label = "y = {0:.4f}x + {1:.4f}\nR^2 = {2:.4f}".format(a[0][0], b[0], r2)
        ax.text(x.min(), y.min(), label, fontdict={'fontsize': 8})

        idx = idx + 1

    plt.tight_layout()
    plt.show()


if __name__ == "__main__":
    # liner_regression('CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT')
    liner_regression('RM', 'AGE', 'TAX', 'B')

以下のようなエラーがでるので、指示に従って、x.reshape(-1, 1) としています。

Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.

https://stackoverflow.com/questions/35082140/preprocessing-in-scikit-learn-single-sample-depreciation-warning

>>> import pandas as pd
>>> df = pd.DataFrame([1,2,3])
>>> df.columns = ['x']
>>> x = df['x']
x
0    1
1    2
2    3
Name: x, dtype: int64
>>> x.reshape((-1,1))
array([[1],
       [2],
       [3]])

LinearRegressionのAPIについて以下サイトから引用させてもらいます。

https://pythondatascience.plavox.info/scikit-learn/%E7%B7%9A%E5%BD%A2%E5%9B%9E%E5%B8%B0

sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False,
                                      copy_X=True, n_jobs=1)
パラメータ 内容
fit_intercept False に設定すると切片を求める計算を含めない。目的変数が原点を必ず通る性質のデータを扱うときに利用。 (デフォルト値: True)
normalize True に設定すると、説明変数を事前に正規化します。 (デフォルト値: False)
copy_X メモリ内でデータを複製してから実行するかどうか。 (デフォルト値: True)
n_jobs 計算に使うジョブの数。-1 に設定すると、すべての CPU を使って計算します。 (デフォルト値: 1)
属性 内容
coef_ 偏回帰係数
intercept_ 切片
メソッド 内容
fit(X, y[, sample_weight]) 線形回帰モデルのあてはめを実行
get_params([deep]) 推定に用いたパラメータを取得
predict(X) 作成したモデルを利用して予測を実行
score(X, y[, sample_weight]) 決定係数 R2を出力
set_params(**params) パラメータを設定

line_reg

1.相関分析

相関分析とは、二種類のデータの関係の強さを相関係数で表現する分析手法

分析の手順は

  1. 散布図を描く
  2. 散布図をみて関連性を推測

相関係数とは、

  1. 2変数間の関連性の強さを図る
  2. 一般的に小文字のr (correlation) であらわす
  3. 常に -1 ~ 1 の間の値をとる
  4. 正の値の場合、正の相関、負の値の場合、負の相関がある

相関係数の強弱

相関係数 相関の強さ
~ 0.3未満 ほぼ無相関
0.3 ~ 0.5未満 非常に弱い相関
0.5 ~ 0.7未満 相関がある
0.7 ~ 0.9未満 強い相関
0.9以上 非常に強い相関

2.散布図を描く

基本統計量、ヒストグラムで使用したボストンの住宅価格のデータセットの各説明変数(x) と 住宅価格の中央値(y) の散布図を描く。

以下のサイトから引用

https://pythondatascience.plavox.info/matplotlib/%E6%95%A3%E5%B8%83%E5%9B%B3

matplotlib.pyplot.scatter(x, y, s=20, c=None, marker='o', cmap=None, norm=None,
                          vmin=None, vmax=None, alpha=None, linewidths=None,
                          verts=None, edgecolors=None, hold=None, data=None,
                          **kwargs)
パラメータ 内容
x.y グラフに出力するデータ
s サイズ (デフォルト値: 20)
c 色、または、連続した色の値
marker マーカーの形 (デフォルト値: ‘o’= 円)
cmap カラーマップ。c が float 型の場合のみ利用可能です。
norm c を float 型の配列を指定した場合のみ有効。正規化を行う場合の Normalize インスタンスを指定。
vmin,vmax 正規化時の最大、最小値。 指定しない場合、データの最大・最小値となります。norm にインスタンスを指定した場合、vmin, vmax の指定は無視されます。
alpha 透明度。0(透明)~1(不透明)の間の数値を指定。
linewidths線の太さ。
edgecolors 線の色。

from sklearn import datasets
import pandas as pd
import matplotlib.pyplot as plt
import math

def correl_sccater(*feature_index):
    """
    https://pythondatascience.plavox.info/matplotlib/%E6%95%A3%E5%B8%83%E5%9B%B3
    :return:
    """
    boston = datasets.load_boston()

    df_ex = pd.DataFrame(boston.data)
    df_ex.columns = boston.feature_names
    import pprint
    print(pprint.pprint(df_ex))

    df_res = pd.DataFrame(boston.target)
    df_res.columns = ['Price']

    y = df_res['Price']
    fig = plt.figure()

    cnt = len(feature_index)
    cols = 1 if cnt == 1 else (2 if cnt < 6 else 4)
    rows = math.ceil(cnt / cols)
    idx = 1
    for feature in feature_index:

        x = df_ex[feature]
        ax = fig.add_subplot(rows, cols, idx)

        ax.set_title(feature, fontdict={'fontsize': 10}, pad=2)
        ax.scatter(x, y, s=0.5)
        idx = idx + 1

    plt.tight_layout()
    plt.show()


if __name__ == "__main__":
    correl_sccater('CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT')
    #correl_sccater('RM')

scatter

1.正規分布と確率密度関数

1.1 正規分布

  • 正規分布は、数式(確率密度関数)で表現できる。
    • データの中心を示す平均(μ)とバラツキの大きさを示す標準偏差(σ)がわかれば、正規分布の形が決まる
  • 平均値(μ)を中心に左右対称の釣り鐘型に分布
  • 平均値、中央値、最頻値が一致
  • グラフで囲まれた部分が確率を表し、全体の合計が1となる
  • 対応する面積を求めると確率が求まる

1.2 σ区間

確率密度関数の範囲について定積分(面積を求める)ことで、確率が求まる。

区間 範囲開始 範囲終了 正規分布の場合収まる確率
1σ 区間 平均(μ) - 標準偏差(σ) 平均(μ) + 標準偏差(σ) 約 68.27%
2σ 区間 平均(μ) - 2*標準偏差(σ) 平均(μ) + 2*標準偏差(σ) 約 95.45%
3σ 区間 平均(μ) - 3*標準偏差(σ) 平均(μ) + 3*標準偏差(σ) 約 99.73%

1.3 試してみる

基本統計量の確認で使用したデータセット について、正規分布と仮定しグラフを描画、また、σ区間の確率を定積分により計算。

from sklearn import datasets
import pandas as pd
import matplotlib.pyplot as plt
import math
import numpy as np
from scipy.stats import norm
from scipy import integrate


def normal_dist():
    """
    https://ja.wikipedia.org/wiki/%E7%A2%BA%E7%8E%87%E5%AF%86%E5%BA%A6%E9%96%A2%E6%95%B0
    https://mathtrain.jp/gaussdistribution
    https://mathtrain.jp/pmitsudo
    https://logics-of-blue.com/%E7%A2%BA%E7%8E%87%E5%AF%86%E5%BA%A6%E9%96%A2%E6%95%B0%E3%81%A8%E6%AD%A3%E8%A6%8F%E5%88%86%E5%B8%83/
    :return:
    """
    boston = datasets.load_boston()

    df = pd.DataFrame(boston.target)
    df.columns = ['Price']

    x = df['Price']
    # CSVに出力
    # x.to_csv('~/work/house_price.csv')

    import pprint
    print(pprint.pprint(dir(x)))

    fig = plt.figure()
    # 2 * 1 の マトリックス 1番目のセルにグラフを描画
    ax = fig.add_subplot(2,1,1)
    ax.set_title('Boston house price')
    ax.hist(x, bins=int(round(math.sqrt(x.count()), 0)),
            rwidth=0.8, label='house price(x $1,000)')

    # 2 * 1 の マトリックス 2番目のセルにグラフを描画
    ax2 = fig.add_subplot(2, 1, 2)
    nx = np.arange(df.min(), df.max(), 1.0)

    # 確率密度関数(probability density function、PDF)を ラムダにラップし、
    # 関数にする(σ区間算出用)
    pdf = lambda px : norm.pdf(px, loc=x.mean(), scale=x.std())

    ax2.plot(nx, pdf(nx))

    # σ区間の確率を算出(定積分)
    sig = []
    for i in range(1, 4, 1):
        s, s1e = integrate.quad(pdf, x.mean() - (x.std() * i), x.mean() + (x.std() * i))
        sig.append(s)

    label = """
     mean={0:f}
     standard deviation={1:f}
     1σ : {2:f} 
     2σ : {3:f}
     3σ : {4:f}
     """.format(
        x.mean(),
        x.std(),
        sig[0], sig[1], sig[2])

    ax2.text(27, 0.01, label)


    plt.show()

if __name__ == "__main__":
    normal_dist()

normal