「入門はじめての多変量解析」をPythonで写経 Vol.1 ~ 1章「多変量解析は楽しい!」多変量解析とは、統計・行列の超基礎
1章「多変量解析は楽しい!」
書籍の著者 石村貞夫 先生、石村光資郎 先生
書籍「入門はじめての多変量解析」1章「多変量解析は楽しい!」の Python写経活動記録 です。
多変量解析の入門を Python と一緒に学ぶ写経シリーズです。
1章は多変量解析の概要、よく使う統計のおさらいの章です。
この記事は、ChatGPTによる多変量解析の紹介 と 統計・行列の超基礎 を取り扱います。
ChatGPT 活用型学習で進めてまいります!
では書籍を開いて多変量解析の旅に出かけましょう🚀

はじめに
このブログシリーズは、書籍「入門はじめての多変量解析」(東京図書、「テキスト」と呼びます)の Python 写経を通じて得た「多変量解析の楽しさ」をご紹介します。
書籍の紹介と引用表記はリンク先の記事に掲載しています。
1章 多変量解析は楽しい
この記事は1章の以下のSectionを取り扱います。
1.1 What's 多変量解析?
1.2 重回帰分析のはなし
1.3 主成分分析のはなし
1.4 因子分析のはなし
1.5 判別分析のはなし
1.6 クラスター分析のはなし
1.7 数量化理論のはなし
1.8 ここでちょっと復習!
記事に用いるデータは、テキストに掲載されたデータそのものを引用しています。
データ件数の少ないものはコード上でデータを登録し、データ件数の多いものはCSVファイル化してデータを読み込みしています。
1章で用いるライブラリをインポートします。
### インポート
# 数値計算
import numpy as np
import pandas as pd
import sympy as sp
# 統計
import statistics
import pingouin as pg
import scipy.stats as stats
# 機械学習
from sklearn.preprocessing import StandardScaler
# 描画
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Meiryo' # または import japanize_matplotlib
# TeX表示
from IPython.display import Math
イントロダクション
ChatGPT が教えてくれた「多変量解析の紹介」をお読み下さい。
これから進む「多変量解析の旅」の粗い地図です。
1章「多変量解析は楽しい!」のご紹介✨
多変量解析の世界をざっくりのぞいてみましょう🎉
「こんな面白い手法があるんだ!」とワクワクしながら、2章以降の学びへの期待を高める6つのテーマをご紹介します😊
1.重回帰分析 🎯 【2章】
概要:
複数の要因(説明変数)が結果(目的変数)にどう影響するかを一気に見通す魔法のような手法です✨利用シーン:
売上高を「広告費」「価格」「季節要因」で予測したいとき🏪
人事評価を「勤続年数」「業務量」「満足度」で説明したいとき👥
キーポイント:
説明変数が結果にどんな影響を与えるか、係数の数字からじんわり感じてみましょう(回帰係数の解釈)🔢
モデルがデータをどれくらいキレイに説明できているかをチェックする(R²やAICなど)(モデル適合度)📊
カテゴリ変数を数字に置き換えて使うコツをつかむ(ダミー変数)🏷️
変数同士が仲良くなりすぎないように注意する(多重共線性)⚠️

2.主成分分析 🔍 【3章】
概要:
高次元データをグッと視覚化しやすくして、隠れたパターンを発見する次元圧縮のヒーローです🚀利用シーン:
顧客アンケートの回答(100項目以上!)を2〜3次元でプロットしたいとき📊
IoTセンサーの大量データを要約して異常検知したいとき⚙️
キーポイント:
データのバラつきをぐっと集める軸を探すイメージで(固有ベクトル・固有値)📈
各データが主成分上でどこにいるかをスコアでチェックする(主成分得点)🎯
大事な情報をどれだけギュッと保存できているかを示す(累積寄与率)📊

3.因子分析 🧩 【4章】
概要:
観測データの背後にある“見えない要素”をパズル感覚で組み立てる分析法です🔎利用シーン例:
心理テストの回答から「性格因子」を抽出したいとき🧠
商品評価の多次元データから「品質」「デザイン」「価格満足度」の潜在因子を探るとき🛍️
キーポイント:
どの項目が隠れた要素と仲良しなのかを探る(因子負荷量)📌
データの奥にある要素をくみ出すやり方のイメージをつかむ(因子抽出法)🧮
因子をくるっと回して、見やすく整えるイメージ(因子回転)🔄

4.判別分析 🛡️ 【5章】
概要:
データがどのグループに属するかをビシッと見分ける分類の達人です💼利用シーン例:
メールを「迷惑メール/通常メール」に振り分けたいとき📧
顧客を「高リスク/低リスク」に判定して与信審査したいとき🏦
キーポイント:
グループをわける判別スコアの感覚をつかむ(判別得点)📈
データの距離感を図ってグループ分けの決め手に(マハラノビス距離)📐
正しく分けられた割合と、ときどき間違う割合も意識しましょう(正答率と誤判別率)⚖️

5.クラスター分析 🌳 【6章】
概要:
似た者同士を自動でグループ分け!
データを“自然なまとまり”に分割して思わぬ発見をもたらします🎈利用シーン例:
顧客セグメンテーションでマーケティング施策を最適化したいとき🎯
商品ラインアップを特徴別にまとめたいとき📦
キーポイント:
グループ同士の距離感をざっくり比べてみる(クラスタ間の距離)📐
樹形図でグループのつながりをワイワイ見る(デンドログラム)🌳

6.数量化理論 ✨ 【7~9章】
概要:
カテゴリカルデータ(性別・職業・アンケート回答など)を数値化し、統計解析に乗せる理論です📊利用シーン例:
アンケート結果を回帰分析に組み込みたいとき✉️
クロス集計表から見えにくい傾向を探りたいとき🔄
キーポイント:
Ⅰ~Ⅲ類のうち、データの特性に合わせてゆるく使い分ける🔄(数量化理論Ⅰ〜Ⅲ類)
カテゴリ数量(カテゴリごとの数値スコアの算出)(カテゴリ数量)🔢
アンケート例:名義尺度(性別)や順序尺度(満足度5段階)を数値化して解析に活用(実例:アンケートデータ)📈
どの手法も、2章以降でじっくりステップ・バイ・ステップに解説します!
まずは「こんな世界があるんだ!」というワクワク感を胸に、次章へ進んでみてくださいね😊🔜✨
わくわくした人、手を挙げて~✋️✨️
テキストの Section 1.1 ~ 1.7 には「多変量解析の概要」がもっと具体的に書かれていますので、ぜひお読み下さい!

Section 1.8 ここでちょっと復習!
ここから記事はガラッと変わります。
テキストは、多変量解析の読み解きには「統計・行列の基礎知識」が大切だとして、「ここでちょっと復習!」節を設けています。
Python を活用して基礎知識を確認していきましょう。
■ データの読み込み
テキスト p.23 表1.8.4 の身長・体重データを引用します。
この「身長・体重データ」を使って、統計・行列の復習を行います。
データをリストに設定した後に、pandas データフレームに読み込みます。
### データ p.23 表1.8.4
# データの登録
height = [151, 164, 146, 158]
weight = [48, 53, 45, 61]
# データフレーム化
data1 = pd.DataFrame({'身長': height, '体重': weight}, index=range(1, 5))
data1.index.name = 'No.'
# 結果の表示
data1【実行結果】
4人の身長・体重データです。

散布図を描いてデータの概観を掴みましょう。
pandas の plot.scatter() を利用します。
# 散布図の描画
data1.plot.scatter(x='身長', y='体重', s=70),
plt.xlim(140, 168)
plt.ylim(38, 65);【実行結果】
身長・体重の値の範囲、身長・体重の関係性などを読み取れそうです。


基礎的な統計量
■ 平均 p.23
4つの身長データを足して4で割ると、身長の平均値になります。
4つの体重データを足して4で割ると、体重の平均値になります。
Python の複数のライブラリで平均を計算しましょう。
簡単な文法ですので、ぜひ覚えてしまいましょう。
🖲️Python の組み込み関数 sum()、len()
リストのデータを使います。
### 平均 p.23
# Python組み込み関数利用 sum: 合計, len: 個数
height_mean = sum(height) / len(height)
weight_mean = sum(weight) / len(weight)
print(f'身長の平均: {height_mean}, 体重の平均: {weight_mean}') 【実行結果】

🖲️Python の標準ライブラリ statistics の mean()
リストのデータを使います。
他のライブラリを含め、平均は「mean」の名称が多いです。
(average じゃなかったのか…)
# Python標準ライブラリ利用
height_mean = statistics.mean(height)
weight_mean = statistics.mean(weight)
print(f'身長の平均: {height_mean}, 体重の平均: {weight_mean}')【実行結果】

🖲️numpy の mean()
こちらも mean です。
リストのデータを使います。
# numpy利用
height_mean = np.mean(height)
weight_mean = np.mean(weight)
print(f'身長の平均: {height_mean}, 体重の平均: {weight_mean}')【実行結果】

🖲️pandas の mean()
こちらも mean です。
データフレームの後ろに「.mean()」とつなげます。
# pandas利用
data1.mean().rename('平均').to_frame()【実行結果】


■ 分散 p.24
データのバラツキを示す統計量です。
テキストに合わせて分母に「データの個数 - 1」を用いる「標本分散」を計算します。
数式にするとこんな感じ…
$$
s_x^2 = \cfrac{1}{N-1}\ \sum_{i=1}^N (x_i - \bar{x})^2
$$
$${x_i}$$ は個々のデータ、$${\bar{x}}$$ はデータの平均、$${N}$$ はデータの個数(標本サイズ)です。
では Python に進みましょう。
🖲️Python の組み込み関数 sum()、len()
先程の数式どおりに実装しています。
### 分散 p.24 ※テキストが標本分散と呼ぶ、不偏分散
# Python組み込み関数利用
height_var = sum([(h - height_mean)**2 for h in height]) / (len(height) - 1)
weight_var = sum([(w - weight_mean)**2 for w in weight]) / (len(weight) - 1)
print(f'身長の分散: {height_var}, 体重の分散: {weight_var}')【実行結果】

角カッコで書いた以下のコードは「リスト内包表記」という Python の書き方です。
[(h - height_mean)**2 for h in height]身長データから1つづつデータを取り出して、平均を引いた二乗(偏差平方と呼びます)を計算して、角カッコで括った「リスト」に格納しています。
🖲️Python の標準ライブラリ statistics の variance()
リストのデータを使います。
variance は「分散」のことです。
statistics の variance() は標本分散を計算します。
# Python標準ライブラリ利用
height_var = statistics.variance(height)
weight_var = statistics.variance(weight)
print(f'身長の分散: {height_var}, 体重の分散: {weight_var}')【実行結果】

🖲️numpy の var()
var は variance を短くした感じです。
リストのデータを使います。
「ddof=1」とは 分母の $${N-1}$$ の $${1}$$ のことです。
# numpy利用
height_var = np.var(height, ddof=1)
weight_var = np.var(weight, ddof=1)
print(f'身長の分散: {height_var}, 体重の分散: {weight_var}')【実行結果】

🖲️pandas の var()
こちらも var です。
データフレームの後ろに「.var()」とつなげます。
# pandas利用
data1.var(ddof=1).rename('標本分散').to_frame()【実行結果】


■ 標準偏差 p.24
標準偏差もデータのバラツキを示す統計量です。
分散の正の平方根です。
分散はデータの単位が「二乗」されていますが、標準偏差はデータの単位に戻っています。
身長の場合、分散の単位は $${\text{cm}^2}$$、標準偏差の単位は $${\text{cm}}$$ です。
数式にするとこんな感じ…
$$
s_x = \sqrt{\cfrac{1}{N-1}\ \sum_{i=1}^N (x_i - \bar{x})^2}
$$
🖲️Python の組み込み関数 sum()、len()
先程の数式どおりに実装しています。
### 標準偏差 p.24 ※テキストが標本分散と呼ぶ、不偏分散の標準偏差
# Python組み込み関数利用
height_std = (sum([(h - height_mean)**2 for h in height]) / (len(height) - 1))**(1/2)
weight_std = (sum([(w - weight_mean)**2 for w in weight]) / (len(weight) - 1))**(1/2)
print(f'身長の標準偏差: {height_std}, 体重の標準偏差: {weight_std}')【実行結果】

🖲️Python の標準ライブラリ statistics の stdev()
リストのデータを使います。
stdev は 「標準偏差」(standard deviation)のことです。
statistics の stdev() は標本標準偏差(標本分散の正の平方根)を計算します。
# Python標準ライブラリ利用
height_std = statistics.stdev(height)
weight_std = statistics.stdev(weight)
print(f'身長の標準偏差: {height_std}, 体重の標準偏差: {weight_std}')【実行結果】

🖲️numpy の std()
std は standard deviation を短くした感じです。
リストのデータを使います。
「ddof=1」とは 分母の $${N-1}$$ の $${1}$$ のことです。
# numpy利用
height_std = np.std(height, ddof=1)
weight_std = np.std(weight, ddof=1)
print(f'身長の標準偏差: {height_std}, 体重の標準偏差: {weight_std}')【実行結果】

🖲️pandas の std()
こちらも std です。
データフレームの後ろに「.std()」とつなげます。
# pandas利用
data1.std(ddof=1).rename('標準偏差').to_frame()【実行結果】


■ データの標準化 p.25
データの標準化は、データからデータの平均を引いて、データの標準偏差で割ることです。
標準化後のデータは「平均0、標準偏差1」になり、単位がなくなります。
身長や体重のように単位の異なる複数のデータを比べるときに活用します。
機械学習でも頻繁に利用します。
数式にするとこんな感じ…
$$
x_{i_\text{std}} = \cfrac{x_i - \bar{x}}{s_x}
$$
🖲️Python の組み込み関数
Python の関数を作ってみましょう。
standardization() 関数は、データ x_list を受け取って、標準化後のデータを返す関数です。
あわせて、データを表形式で見せるためのデータフレーム化関数を定義します。
### データの標準化 p.25
# Python組み込み関数で関数化
def standardization(x_list):
# データ個数(標本サイズ)の算出
N = len(x_list)
# データの平均の算出
x_bar = sum(x_list) / N
# データの標本標準偏差の算出
s = (sum([(x - x_bar)**2 for x in x_list]) / (N - 1))**(1/2)
# データの標準化
x_std = [(x - x_bar) / s for x in x_list]
# 戻り値 標準化済みデータ
return x_std
# pandasデータフレーム化関数
def make_df(x_list):
df = pd.DataFrame({'身長': x_list[0], '体重': x_list[1]},
index=range(1, len(x_list[0])+1))
df.index.name = 'No.'
return dfこの関数を使ってデータの標準化をしましょう。
# 標準化の実行
height_zscore = standardization(height)
weight_zscore = standardization(weight)
# データフレーム化
make_df([height_zscore, weight_zscore]).round(4)【実行結果】

標準化後のデータが「平均、標準偏差1」になったことを確認します。
# 標準化データの平均と分散
(make_df([height_zscore, weight_zscore]).describe()
.loc[['mean', 'std'], :].round(10))【実行結果】
平均 mean = 0 、標準偏差 std = 1 になっています!

🖲️scipy の zscore()
リストのデータを使います。
zscore は 標準化データの別名「Zスコア」のことです。
# scipy利用
zscores = stats.zscore([height, weight], axis=1, ddof=1)
make_df(zscores).round(4)【実行結果】

🖲️pandas
データフレームに関数を適用する apply() と 関数を簡単に作れる lambda() を用いて、データの標準化の数式どおりのコードを書きます。
# pandas利用
data1.apply(lambda x: (x - x.mean())/ x.std(ddof=1), axis=0).round(4)【実行結果】

🖲️scikit-learn の StandardScaler()
データフレームを使います。
注意点は「標準化に用いる標準偏差は分母が $${N}$$ である($${N-1}$$ ではない)」ことです。
# scikit-learn利用 ※標準偏差はNで割っている(N-1で割っていない)
scaler = StandardScaler()
data1_ss = scaler.fit_transform(data1)
make_df(data1_ss.T).round(4)【実行結果】
他のライブラリとは異なる値になりました。

StandardScaler() は機械学習の文脈でよく使われます。
「標準偏差の分母は $${N}$$ !」を理解しておきましょう。
データの個数=標本サイズが大きい場合、分母の1の違いをあまり気にすることがないかもです。
🚋 ちょっと寄り道 🚋
ChatGPT に scikit-learn で「標準偏差の分母は $${N-1}$$」の実装方法を聞いてみたら、コードを作ってくれました。
scikit-learn ライクな ZScoreScaler 変換器(クラス)です。
### scikit-learnのTransformerでZスコア算出を実装
# 追加インポート
from sklearn.base import BaseEstimator, TransformerMixin
# import numpy as np
class ZScoreScaler(BaseEstimator, TransformerMixin):
def __init__(self, ddof=1):
self.ddof = ddof
def fit(self, X, y=None):
X = np.asarray(X, dtype=float)
self.mean_ = X.mean(axis=0)
self.std_ = X.std(axis=0, ddof=self.ddof)
return self
def transform(self, X):
X = np.asarray(X, dtype=float)
return (X - self.mean_) / self.std_
def inverse_transform(self, X_scaled):
Xs = np.asarray(X_scaled, dtype=float)
return Xs * self.std_ + self.mean_実行してみましょう。
ZScoreScaler() の引数 ddof=1 とすることで、標準偏差の分母が $${N-1}$$ になります。
# 変換器の作成
scaler = ZScoreScaler(ddof=1)
# データの標準化
data1_std = scaler.fit_transform(data1)
# 結果の表示
pd.DataFrame(data1_std, index=data1.index, columns=data1.columns).round(4)【実行結果】
できました!

このクラスのいいところは、元のスケールに逆変換できることです!
# 標準化済みデータを元のスケールに戻す
data1_inv = scaler.inverse_transform(data1_std)
# 結果の表示
pd.DataFrame(data1_inv, index=data1.index, columns=data1.columns).round(4)【実行結果】
標準化前のデータに戻りました!


■ 共分散、共分散行列 p.26, 27
共分散は2つのデータが同じ方向または逆の方向に変動するかを示す指標です。
テキストでは「分散は長さの概念であるのに対し、共分散は広がりの概念です」と説明されています。
数式にするとこんな感じ…
$$
s_{xy} = \cfrac{1}{N-1}\ \sum_{i=1}^N (x_i - \bar{x})(y_i - \bar{y})
$$
🖲️Python の組み込み関数
Python の関数を作ってみましょう。
covariance() 関数は、データ x_list、y_list を受け取って、共分散を返す関数です。
### 共分散 p.26
# Python組み込み関数で関数化
def covariance(x_list, y_list):
# データの個数(標本サイズ)の算出
N = len(x_list)
# 標本平均の算出
x_bar = sum(x_list) / N
y_bar = sum(y_list) / N
# 共分散の算出
s_xy = (sum([(x - x_bar)*(y - y_bar) for x, y in zip(x_list, y_list)])
/ (N - 1))
## 戻り値: 共分散
return s_xyこの関数を使って共分散を計算しましょう。
# 共分散の算出
cov = covariance(height, weight)
print(f'共分散: {cov}')【実行結果】

🖲️Python の標準ライブラリ statistics の covariance()
リストのデータを使います。
covariance は 「共分散」のことです。
statistics の covariance() は標本共分散(分母が $${N-1}$$)を計算します。
# Python標準ライブラリ利用
cov = statistics.covariance(height, weight)
print(f'共分散: {cov}')【実行結果】

🖲️numpy の cov()
cov は covariance を短くした感じです。
リストのデータを使います。
「ddof=1」とは 分母の $${N-1}$$ の $${1}$$ のことです。
計算結果は「分散共分散行列」形式で表示されます。
# numpy利用
cov = np.cov(height, weight, ddof=1)
print(f'分散共分散行列:\n{cov}')【実行結果】
右上と左下の $${38.25}$$ が共分散です。
左上から右下にかけての対角線には 各データの分散が表示されています。

🖲️pandas の cov()
こちらも cov です。
データフレームの後ろに「.cov()」とつなげます。
# pandas利用
data1.cov(ddof=1)【実行結果】
こちらも分散共分散行列の形式です。
変数名が表示されているので、分かりやすいですね!


■ 相関係数、相関行列 p.26, 28
相関係数も共分散と同様に、2つのデータが同じ方向または逆の方向に変動するかを示す指標です。
相関係数は共分散を2つの変数の標準偏差で割ることで、値を $${-1}$$ から $${1}$$ になるようにしています。
数式にするとこんな感じ…
$$
\begin{align*}
r &= \cfrac{\sum_{i=1}^N (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^N (x_i-\bar{x})^2} \sqrt{\sum_{i=1}^N (y_i-\bar{y})^2}} \\
&= \cfrac{s_{xy}}{s_x s_y}
\end{align*}
$$
🖲️Python の組み込み関数
Python の関数を作ってみましょう。
corr() 関数は、データ x_list、y_list を受け取って、相関係数を返す関数です。
### 相関係数 p.27
# Python組み込み関数で関数化
def corr(x_list, y_list):
# データの個数(標本サイズ)の算出
N = len(x_list)
# 標本平均の算出
x_bar = sum(x_list) / N
y_bar = sum(y_list) / N
# 相関係数の分子・分母の算出
numerator = sum([(x - x_bar)*(y - y_bar) for x, y in zip(x_list, y_list)])
denominator1 = sum([(x - x_bar)**2 for x in x_list])**(1/2)
denominator2 = sum([(y - y_bar)**2 for y in y_list])**(1/2)
# 相関係数の算出
r = numerator / (denominator1 * denominator2)
## 戻り値: 相関係数
return rこの関数を使って相関係数を計算しましょう。
# 相関係数の算出
corr = corr(height, weight)
print(f'相関係数: {corr}')【実行結果】

🖲️Python の標準ライブラリ statistics の correlation()
リストのデータを使います。
correlation は 「相関」のことです。
# Python標準ライブラリ利用
corr = statistics.correlation(height, weight)
print(f'相関係数: {corr}')【実行結果】

🖲️numpy の corrcoef()
corrcoef は 相関係数 correlation coefficient を短くした感じです。
リストのデータを使います。
計算結果は「相関行列」形式で表示されます。
# numpy利用
corr = np.corrcoef(height, weight)
print(f'相関行列:\n{corr}')【実行結果】
右上と左下の $${0.693}$$ が相関係数です。
左上から右下にかけての対角線には データ自分自身との相関である $${1}$$ が表示されています。

🖲️pandas の corr()
corr は 相関係数 correlation coefficient を短くした感じです。
データフレームの後ろに「.corr()」とつなげます。
# pandas利用
data1.cov(ddof=1)【実行結果】
こちらも相関行列の形式です。
変数名が表示されているので、分かりやすいですね!

🖲️pingouin の corr()
pingouin 🐧 は統計分野の「かゆいところに手が届く」系のライブラリです。
早速使ってみましょう。
# pingouin利用
pg.corr(height, weight)【実行結果】
$${\text{r}=0.69316}$$ が相関係数です。

左側の「pearson」はこの相関係数の種類が「ピアソンの積率相関係数」であることを示しています。
その他にも相関係数に関連する統計量が表示されています。
テキストは「標準化後のデータの共分散行列は相関行列になる」ことを示唆してます。
試してみましょう!
標準化したデータの共分散を算出して、その値が相関係数とおなじになることを確認します。
### データ標準化後に共分散を算出 p.28
# 標準化の実行
height_zscore = standardization(height)
weight_zscore = standardization(weight)
# 共分散の算出 Python組み込み関数
cov = covariance(height_zscore, weight_zscore)
print(f'共分散: {cov}')【実行結果】
共分散は相関係数と同じ値になりました。

numpy で標準化後データの分散共分散行列が相関行列となることを確認します。
# numpy利用
cov = np.cov(height_zscore, weight_zscore)
print(f'標準化後の分散共分散行列:\n{cov}')【実行結果】
相関行列と同じ値になっています!

平均から相関係数まで、基礎的な統計量を学びました。
少し休憩しましょう。

行列の演算
行列は…

ではありません…😅
数学の「行列」の基礎的な演算を学びます、というか、Python で動かします!
■ 行列の計算と逆行列・行列式 p.29
sympy ライブラリを用いて、変数 $${x_1, x_2, y_1, y_2, s_{11}, s_{12}, s_{21}, s_{22}}$$(の文字)を使って、行列の演算を表現してみましょう!
行列 $${\bm S}$$、ベクトル $${\bm x, \bm y}$$ を設定します。
### 行列・ベクトルの作成 sympy利用
# 変数の定義
x1, x2, y1, y2, s11, s12, s21, s22 = sp.symbols('x1 x2 y1 y2 s11 s12 s21 s22')
# 行列S、列ベクトルx、行ベクトルyの定義
S = sp.Matrix([[s11, s12], [s21, s22]])
x = sp.Matrix([x1, x2])
y = sp.Matrix([y1, y2]).T
# 行列S、列ベクトルx、行ベクトルyの表示
display(Math(f'\Large S={sp.latex(S)}'))
display(Math(f'\Large x={sp.latex(x)}'))
display(Math(f'\Large y={sp.latex(y)}'))【実行結果】
本格的な数式表現です!
この先、数式・公式の表現には sympy を使っていきます!

行列 $${\bm S}$$、ベクトル $${\bm x, \bm y}$$ に具体的な値を設定しましょう。
(個人的に)使い勝手の良い numpy を使います。
### データの作成
S_mat = np.array([[1, 2], [3, 4]])
x_vec = np.array([[3], [5]])
y_vec = np.array([[2, 4]])
print(f'行列S:\n{S_mat}')
print(f'列ベクトルx:\n{x_vec}')
print(f'行ベクトルy:\n{y_vec}')【実行結果】
この先、数値計算は numpy を使っていきます。

◉ 行列の積とは?
内積とかドット積と呼ばれる行列・ベクトルの積を確かめていきます。
① 行列 vs 列ベクトル
・公式
### 行列の積とは? その1 p.29
# 計算式
ans = S * x
display(Math(f'\Large {sp.latex(S)}{sp.latex(x)} = {sp.latex(ans)}'))【実行結果】

・計算例
「@」が行列の積(掛け算)の記号です。
# 計算例
print(S_mat @ x_vec)【実行結果】

② 行ベクトル vs 行列
・公式
### 行列の積とは? その2 p.29
# 計算式
ans = y * S
display(Math(f'\Large {sp.latex(y)}{sp.latex(S)} = {sp.latex(ans)}'))【実行結果】

・計算例
# 計算例
print(y_vec @ S_mat)【実行結果】

③ 行ベクトル vs 列ベクトル
・公式
### 行列の積とは? その3 p.29
# 計算式
ans = y * x
display(Math(f'\Large {sp.latex(y)}{sp.latex(x)} = {sp.latex(ans)}'))【実行結果】

・計算例
# 計算例
print(y_vec @ x_vec)【実行結果】

④ 列ベクトル vs 行ベクトル
・公式
### 行列の積とは? その4 p.29
# 計算式
ans = x * y
display(Math(f'\Large {sp.latex(x)}{sp.latex(y)} = {sp.latex(ans)}'))【実行結果】

・計算例
# 計算例
print(x_vec @ y_vec)【実行結果】

◉ 逆行列とは?
行列の逆行列です。
逆行列が存在しない場合もあります。
・公式
### 逆行列とは? p.29
# 計算式
ans = S.inv()
display(Math(f'\Large {sp.latex(S)}^{{-1}} = \LARGE {sp.latex(ans)}'))【実行結果】

・計算例
numpy の線形代数 linalg の 逆行列関数 inv() を利用します。
# 計算例
print('逆行列 =')
print(np.linalg.inv(S_mat))【実行結果】

◉ 行列式とは?
行列式の計算結果はスカラーになります。
行列式が0のとき、逆行列は存在しません。
・公式
### 行列式とは? p.29
# 変数の定義
a, b, c, d = sp.symbols('a b c d')
# 行列Aの定義
A = sp.Matrix([[a, b], [c, d]])
# 行列Aの表示
display(Math(f'\Large A = {sp.latex(A)}'))
# 行列式の計算
ans = A.det()
# 行列式の表示
detA = sp.matrices.expressions.determinant.Determinant(A)
display(Math(f'\Large \det A = {sp.latex(detA)} = {sp.latex(ans)}'))【実行結果】

・計算例
numpy の線形代数 linalg の 行列式関数 det() を利用します。
# 計算例
A_mat = np.array([[1, 2], [3, 4]])
print('行列A =')
print(A_mat)
print('det A =', np.linalg.det(A_mat).round(10))【実行結果】


■ 固有値と固有ベクトル p.30
行列分解の一種である「固有値分解」で得られるのが、「固有値」と「固有ベクトル」です。
書籍では「主成分分析」で用いられます。
身長・体重データの分散共分散行列の固有値・固有ベクトルを求めます。
行列式と連立方程式を用いた解法はテキストをお読みください。
この記事では numpy と sympy で算出します。
🖲️numpy の eig()
身長・体重データの分散共分散行列 cov を算出して、eig(cov) で固有値・固有ベクトルを算出します。
# numpy利用
# 共分散行列の算出
cov = np.cov(height, weight, ddof=1)
# 固有値・固有ベクトルの算出
eigen_values, eigen_vectors = np.linalg.eig(cov)
# 結果の表示
print(f'固有値:\n{eigen_values}')
print(f'固有ベクトル:\n{eigen_vectors}')【実行結果】
固有値は $${94.410}$$ と $${16.757}$$ の2つです。
固有値 $${94.410}$$ に対応する固有ベクトルは $${[0.765, 0.644]}$$ となり、固有値 $${16.757}$$ に対応する固有ベクトルは $${[-0.644, 0.765]}$$ となりました。

🖲️sympy の eigenvects()
分散共分散行列を行列 Matrix 型 にして、Matrix に対する eigenvects() で固有値・固有ベクトルを算出します。
# sympy利用
# TeX表示の設定
sp.init_printing()
# 共分散行列を行列Aとして定義
A = sp.Matrix(cov)
# 行列Aの固有値・固有ベクトルの表示
display(A.eigenvects())
# TeX表示の解除
sp.init_printing(False)【実行結果】
2つの()が固有値・固有ベクトルのペアです。
numpy の計算結果と一致しています。


記事の最後はChatGPTが締めくくります。
今回はコーヒーにたとえて。
📘 ChatGPTのひとこと:
統計・行列の基礎は、朝のコーヒーを淹れるレシピに似ています☕️
① 豆を量る(データの標準化)
② お湯の温度を確かめる(共分散・相関を理解)
③ ゆっくりドリップする(行列演算で情報を引き出す)
このステップを試してみてコーヒーの味わいが深まるように、あなたのデータの見方も少しずつ変わっていくことでしょう😊
次回はこのレシピをさらにアップデートして「どの材料が全体の味にどれだけ効いているか」を確かめる重回帰分析に進みます✨
日常のちょっとした場面でデータに目を向けるたび、思わぬヒントがあなたを待っています。
それでは、次回も「データレシピ」を一緒にかたちにしていきましょう☕️
今回の写経は以上です。
シリーズの記事
次の記事
前の記事
目次
ブログの紹介
note で7つのシリーズ記事を書いています。
ぜひ覗いていってくださいね!
1.のんびり統計
統計検定2級の問題集を手がかりにして、確率・統計をざっくり掘り下げるブログです。
雑談感覚で大丈夫です。ぜひ覗いていってくださいね。
統計検定2級公式問題集CBT対応版に対応しています。
Python、EXCELのサンプルコードの配布もあります。
2.実験!たのしいベイズモデリング1&2をPyMC Ver.5で
書籍「たのしいベイズモデリング」・「たのしいベイズモデリング2」の心理学研究に用いられたベイズモデルを PyMC Ver.5で描いて分析します。
この書籍をはじめ、多くのベイズモデルは R言語+Stanで書かれています。
PyMCの可能性を探り出し、手軽にベイズモデリングを実践できるように努めます。
身近なテーマ、イメージしやすいテーマですので、ぜひぜひPyMCで動かして、一緒に楽しみましょう!
3.実験!岩波データサイエンス1のベイズモデリングをPyMC Ver.5で
書籍「実験!岩波データサイエンスvol.1」の4人のベイジアンによるベイズモデルを PyMC Ver.5で描いて分析します。
この書籍はベイズプログラミングのイロハをざっくりと学ぶことができる良書です。
楽しくPyMCモデルを動かして、ベイズと仲良しになれた気がします。
みなさんもぜひぜひPyMCで動かして、一緒に遊んで学びましょう!
4.楽しい写経 ベイズ・Python等
ベイズ、Python、その他の「書籍の写経活動」の成果をブログにします。
主にPythonへの翻訳に取り組んでいます。
写経に取り組むお仲間さんのサンプルコードになれば幸いです🍀
5.RとStanではじめる心理学のための時系列分析入門 を PythonとPyMC Ver.5 で
書籍「RとStanではじめる心理学のための時系列分析入門」の時系列分析をPythonとPyMC Ver.5 で実践します。
この書籍には時系列分析のテーマが盛りだくさん!
時系列分析の懐の深さを実感いたしました。
大好きなPythonで楽しく時系列分析を学びます。
6.データサイエンスっぽいことを綴る
統計、データ分析、AI、機械学習、Pythonのコラムを不定期に綴っています。
統計・データサイエンス書籍にまつわる記事が多いです。
「統計」「Python」「数学とPython」「R」のシリーズが生まれています。
7.Python機械学習プログラミング実践記
書籍「Python機械学習プログラミング PyTorch & scikit-learn編」を学んだときのさまざまな思いを記事にしました。
この書籍は、scikit-learnとPyTorchの教科書です。
よかったらぜひ、お試しくださいませ。
最後までお読みいただきまして、ありがとうございました。
いいなと思ったら応援しよう!
応援ありがとうございます。これからもがんばって記事を作成します!