線形代数学 講義ノート - 第47回
1. 講義情報と予習ガイド
講義回: 第47回 テーマ: 線形代数の応用としてのデータサイエンス 関連項目: 固有値分解、特異値分解、主成分分析、因子分析、次元削減法 予習内容: - 固有値・固有ベクトルの基本概念 - 特異値分解(SVD)の基本 - 主成分分析(PCA)の目的と手法 - 因子分析の基本的な考え方
2. 学習目標
- 線形代数学の主要概念(固有値・特異値分解・主成分分析・因子分析)の統合的理解
- これらの手法がデータサイエンス、特に健康データ分析においてどのように応用されるかを理解する
- 線形手法と非線形手法の違いと使い分けについて理解する
- 最新の次元削減手法について概観し、その応用可能性を把握する
3. 基本概念の総括
3.1 固有値・固有ベクトルの復習
定義: 行列\(A\)に対して、\(Av = \lambda v\) (\(v \neq 0\))を満たすスカラー\(\lambda\)を固有値、ベクトル\(v\)を対応する固有ベクトルと呼ぶ。
固有値・固有ベクトルは、線形変換の本質的な特性を表しており、以下の重要な性質を持ちます:
- 固有ベクトルは線形変換の下で方向が保存されるベクトル
- 固有値はそのベクトルがどれだけ伸縮されるかを表す係数
- \(n \times n\)行列は最大\(n\)個の固有値を持つ
- 対称行列の固有値はすべて実数であり、固有ベクトルは互いに直交する
固有値問題は以下のように定式化されます: \((A - \lambda I)v = 0\)
非自明な解が存在するための条件: \(\det(A - \lambda I) = 0\)
この方程式を特性方程式と呼び、これを解くことで固有値を求めることができます。
3.2 特異値分解(SVD)の復習
定義: \(m \times n\)行列\(A\)の特異値分解は、\(A = U\Sigma V^T\)と表される。ここで、\(U\)は\(m \times m\)の直交行列、\(V\)は\(n \times n\)の直交行列、\(\Sigma\)は\(m \times n\)の対角行列で、対角成分には\(A\)の特異値が大きい順に並べられている。
特異値分解の重要な特徴:
- すべての行列(実数または複素数)に対して特異値分解が存在する
- 特異値は\(A^T A\)の固有値の平方根
- 左特異ベクトル(\(U\)の列)は\(AA^T\)の固有ベクトル
- 右特異ベクトル(\(V\)の列)は\(A^T A\)の固有ベクトル
- 低ランク近似の最適性(エッカート・ヤングの定理)
SVDは以下の幾何学的解釈を持ちます: 1. \(V^T\)による回転 2. \(\Sigma\)による軸方向の伸縮 3. \(U\)による回転
3.3 主成分分析(PCA)の復習
定義: 主成分分析は、データの分散が最大となる方向(主成分)を見つけ、元のデータをより少ない次元で表現する手法である。
PCAの主な特徴:
- データの共分散行列の固有ベクトルが主成分となる
- 固有値が大きい順に主成分を選ぶことで、情報損失を最小化しながら次元削減が可能
- 各主成分は互いに直交する
- データの標準化の有無により結果が大きく変わる場合がある
PCAの計算手順: 1. データ行列\(X\)を中心化(平均を0にする) 2. 共分散行列\(C = \frac{1}{n-1}X^T X\)を計算 3. \(C\)の固有値と固有ベクトルを計算 4. 固有値の大きさでソートし、対応する固有ベクトルを主成分とする 5. 選択した主成分にデータを射影する
3.4 因子分析の復習
定義: 因子分析は、観測変数の背後にある潜在的な因子(共通因子)を見つけ出す手法である。観測変数\(X\)は、共通因子\(F\)と固有因子\(\epsilon\)により、\(X = \Lambda F + \epsilon\)と表現される。
因子分析の主な特徴:
- 因子負荷量行列\(\Lambda\)は、観測変数と因子の関係性を表す
- 共通性は、共通因子によって説明される分散の割合
- 独自性は、固有因子によって説明される分散の割合
- 因子回転により、解釈のしやすい因子構造を得ることができる
PCAと因子分析の主な違い: - PCAは分散の最大化を目的とするが、因子分析は共分散構造のモデル化を目的とする - PCAは記述的手法だが、因子分析は潜在変数モデルという統計モデルに基づく - 因子分析では共通因子と固有因子を明示的に区別する
4. 健康データ分析における応用事例
4.1 医療画像解析におけるSVD
医療画像処理において、SVDは以下のような用途で活用されています:
- 画像の圧縮とノイズ除去
- MRIやCTスキャン画像の保存と転送の効率化
-
ノイズの多い画像から本質的な情報を抽出
-
特徴抽出
- 画像から診断に有用な特徴を抽出
- 異常検出のための基準となるパターンの識別
実際の応用例: - 乳房X線画像(マンモグラム)からの腫瘍検出 - 網膜画像からの糖尿病性網膜症の自動診断 - 脳MRI画像からの脳卒中や腫瘍の識別
SVDによる画像処理の基本的なアプローチ:
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
# 画像を読み込み、グレースケールに変換
img = Image.open('medical_image.jpg').convert('L')
img_array = np.array(img)
# SVDの計算
U, s, Vt = np.linalg.svd(img_array, full_matrices=False)
# 異なる特異値の数で画像を再構成
for k in [5, 10, 20, 50]:
# 上位k個の特異値だけを使用
s_k = np.zeros_like(s)
s_k[:k] = s[:k]
# 画像の再構成
img_reconstructed = U @ np.diag(s_k) @ Vt
# 結果の表示
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.imshow(img_array, cmap='gray')
plt.title('原画像')
plt.subplot(1, 2, 2)
plt.imshow(img_reconstructed, cmap='gray')
plt.title(f'上位{k}個の特異値で再構成')
plt.show()
4.2 生体信号のPCAによる特徴抽出
生体信号(心電図、脳波、筋電図など)は高次元かつノイズを含むため、PCAによる前処理が有効です:
- ノイズ除去と次元削減
- 多チャンネル脳波(EEG)データから意味のある信号成分の抽出
-
計測時のアーティファクト(体動など)の除去
-
パターン発見
- 睡眠段階の識別
- てんかん発作の予測
- 脳-コンピュータインターフェース(BCI)の精度向上
心電図データのPCA処理例:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
# 多チャンネル心電図データを読み込む (例: 12誘導心電図)
# 形状: [サンプル数, チャンネル数]
ecg_data = np.load('ecg_data.npy')
# データの標準化
ecg_standardized = (ecg_data - np.mean(ecg_data, axis=0)) / np.std(ecg_data, axis=0)
# PCAの適用
pca = PCA()
ecg_pca = pca.fit_transform(ecg_standardized)
# 寄与率の確認
explained_variance_ratio = pca.explained_variance_ratio_
cumulative_variance_ratio = np.cumsum(explained_variance_ratio)
# 寄与率のプロット
plt.figure(figsize=(10, 6))
plt.bar(range(1, len(explained_variance_ratio) + 1), explained_variance_ratio)
plt.plot(range(1, len(cumulative_variance_ratio) + 1), cumulative_variance_ratio, 'r-o')
plt.axhline(y=0.9, color='g', linestyle='-')
plt.xlabel('主成分')
plt.ylabel('寄与率')
plt.title('心電図データの主成分分析')
plt.show()
# 上位2成分でのデータの可視化
plt.figure(figsize=(10, 8))
plt.scatter(ecg_pca[:, 0], ecg_pca[:, 1])
plt.xlabel('第1主成分')
plt.ylabel('第2主成分')
plt.title('心電図データの主成分平面への射影')
plt.show()
4.3 健康質問票の因子分析
健康関連質問票や患者報告アウトカム(PRO)の分析に因子分析が広く使われています:
- 尺度開発と評価
- 質問項目の背後にある潜在的な健康概念の抽出
-
質問票の構造的妥当性の検証
-
心理的・身体的健康状態の評価
- うつ病や不安障害の評価尺度の分析
- 生活の質(QOL)質問票の解釈
健康質問票の因子分析例:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from factor_analyzer import FactorAnalyzer
from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity
from factor_analyzer.factor_analyzer import calculate_kmo
# 健康質問票データの読み込み
health_survey = pd.read_csv('health_survey_data.csv')
# Bartlettの球面性検定
chi_square_value, p_value = calculate_bartlett_sphericity(health_survey)
print(f'Bartlettの球面性検定: chi^2 = {chi_square_value}, p = {p_value}')
# KMO (Kaiser-Meyer-Olkin) 指標
kmo_all, kmo_model = calculate_kmo(health_survey)
print(f'KMO: {kmo_model}')
# 因子数の決定 (スクリープロット)
fa = FactorAnalyzer()
fa.fit(health_survey)
ev, v = fa.get_eigenvalues()
plt.figure(figsize=(10, 6))
plt.scatter(range(1, len(ev) + 1), ev)
plt.plot(range(1, len(ev) + 1), ev)
plt.axhline(y=1, color='r', linestyle='-')
plt.title('スクリープロット')
plt.xlabel('因子数')
plt.ylabel('固有値')
plt.show()
# 因子分析の実施(因子数3と仮定)
fa = FactorAnalyzer(n_factors=3, rotation='varimax')
fa.fit(health_survey)
# 因子負荷量の表示
factor_loadings = fa.loadings_
loadings_df = pd.DataFrame(factor_loadings,
index=health_survey.columns,
columns=[f'因子{i+1}' for i in range(3)])
print("因子負荷量:")
print(loadings_df)
# 共通性の表示
communalities = fa.get_communalities()
communalities_df = pd.DataFrame({'項目': health_survey.columns, '共通性': communalities})
print("\n共通性:")
print(communalities_df)
4.4 遺伝子発現データの次元削減
遺伝子発現データは典型的な高次元データであり、次元削減手法が不可欠です:
- 遺伝子発現プロファイルの分析
- 数万の遺伝子発現レベルから重要なパターンを抽出
-
疾患サブタイプの同定や予後予測
-
シングルセルRNA-seq分析
- 細胞タイプの同定
- 細胞分化経路の解明
遺伝子発現データへのPCA適用例:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# 遺伝子発現データの読み込み
# 行:サンプル、列:遺伝子
gene_expr = pd.read_csv('gene_expression_data.csv', index_col=0)
sample_info = pd.read_csv('sample_info.csv', index_col=0) # サンプルの属性情報
# データの標準化
scaler = StandardScaler()
gene_expr_scaled = scaler.fit_transform(gene_expr)
# PCAの適用
pca = PCA()
gene_expr_pca = pca.fit_transform(gene_expr_scaled)
# 寄与率のプロット
plt.figure(figsize=(10, 6))
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.axhline(y=0.7, color='r', linestyle='-')
plt.xlabel('主成分数')
plt.ylabel('累積寄与率')
plt.title('遺伝子発現データのPCA累積寄与率')
plt.show()
# サンプルの可視化(上位2主成分)
plt.figure(figsize=(12, 10))
for category in sample_info['disease_status'].unique():
mask = sample_info['disease_status'] == category
plt.scatter(gene_expr_pca[mask, 0], gene_expr_pca[mask, 1], label=category, alpha=0.7)
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.title('遺伝子発現データのPCA可視化')
plt.legend()
plt.grid(True)
plt.show()
# 寄与率の高い遺伝子の特定
loading_scores = pd.DataFrame(pca.components_.T, columns=[f'PC{i+1}' for i in range(5)], index=gene_expr.columns)
top_genes = loading_scores.abs().sort_values(by='PC1', ascending=False).index[:20]
print("PC1に大きく寄与する上位20遺伝子:")
print(top_genes)
5. 最新研究動向
5.1 非線形次元削減法
線形手法(PCA、因子分析)では捉えきれない複雑な非線形構造を持つデータに対して、t-SNEやUMAPなどの非線形次元削減法が開発されています:
- t-SNE (t-distributed Stochastic Neighbor Embedding)
- 局所的な類似性を保存する非線形次元削減法
- データポイント間の条件付き確率を使用して、高次元空間での類似性を低次元空間で再現
-
離れたデータ点間の大域的構造より、近接したデータ点間の局所的構造を優先
-
UMAP (Uniform Manifold Approximation and Projection)
- トポロジー的データ解析に基づく次元削減法
- 局所的構造と大域的構造の両方を保存しようとする
- t-SNEより計算効率が良く、大規模データセットに適用可能
両手法の比較: - t-SNEは局所構造の保存に優れるが、大域的構造が失われることがある - UMAPはt-SNEより大域的構造の保存に優れる傾向がある - UMAPはt-SNEより計算が高速 - どちらも非凸最適化問題を解くため、実行ごとに結果が変わりうる
t-SNEとUMAPの実装例:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
import umap
# 高次元データの読み込み(例:健康データ)
high_dim_data = pd.read_csv('high_dim_health_data.csv')
labels = high_dim_data['diagnosis'] # 診断結果など
data = high_dim_data.drop('diagnosis', axis=1)
# t-SNEの適用
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
tsne_results = tsne.fit_transform(data)
# UMAPの適用
umap_reducer = umap.UMAP(random_state=42)
umap_results = umap_reducer.fit_transform(data)
# 結果の可視化と比較
plt.figure(figsize=(16, 6))
# t-SNE
plt.subplot(1, 2, 1)
for label in np.unique(labels):
mask = labels == label
plt.scatter(tsne_results[mask, 0], tsne_results[mask, 1], label=label, alpha=0.7)
plt.title('t-SNE')
plt.legend()
# UMAP
plt.subplot(1, 2, 2)
for label in np.unique(labels):
mask = labels == label
plt.scatter(umap_results[mask, 0], umap_results[mask, 1], label=label, alpha=0.7)
plt.title('UMAP')
plt.legend()
plt.show()
5.2 スパース主成分分析
スパース主成分分析は、通常のPCAに制約を加えて、より解釈しやすい主成分を得る手法です:
- 主な特徴
- 主成分の計算において、一部の変数の重みを正確に0にする(スパース性)
- 少数の重要な変数だけを使って主成分を表現できる
-
解釈性と予測性能のバランスを取る
-
応用例
- 遺伝子発現データから重要な遺伝子セットの同定
- 医療画像の特徴抽出における重要領域の特定
- 医療診断におけるバイオマーカーの選定
スパース主成分分析の実装例:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import SparsePCA
# データの読み込み
data = np.load('health_monitoring_data.npy')
# スパース主成分分析の適用
spca = SparsePCA(n_components=2, alpha=1.0, ridge_alpha=0.01, random_state=42)
spca_results = spca.fit_transform(data)
# 主成分の負荷量(成分)の確認
components = spca.components_
print("スパース主成分の非ゼロ要素の数:")
print([np.sum(comp != 0) for comp in components])
# 結果の可視化
plt.figure(figsize=(12, 6))
# 主成分1の非ゼロ係数
plt.subplot(1, 2, 1)
plt.stem(range(len(components[0])), components[0])
plt.title('第1スパース主成分')
plt.xlabel('変数インデックス')
plt.ylabel('負荷量')
# 主成分2の非ゼロ係数
plt.subplot(1, 2, 2)
plt.stem(range(len(components[1])), components[1])
plt.title('第2スパース主成分')
plt.xlabel('変数インデックス')
plt.ylabel('負荷量')
plt.tight_layout()
plt.show()
5.3 テンソル分解と高次元データ
行列を一般化した多次元配列であるテンソルに対する分解手法が、複雑な多次元構造を持つ健康データ分析で注目されています:
- テンソル分解の主な手法
- CP分解(CANDECOMP/PARAFAC分解)
- Tucker分解
-
テンソル特異値分解(T-SVD)
-
健康データへの応用
- 時系列医療データ(患者 × 測定項目 × 時間)の分析
- 脳機能イメージング(空間 × 時間 × 被験者)の分析
- 薬物反応データ(薬物 × 分子標的 × 細胞種)の分析
テンソル分解の基本的な実装例:
import numpy as np
import matplotlib.pyplot as plt
import tensorly as tl
from tensorly.decomposition import parafac, tucker
# 例:3次元テンソルデータ(患者 × 測定項目 × 時間)
tensor_data = np.load('patient_time_series_tensor.npy')
# CP分解
rank = 3 # テンソルのランク
cp_factors = parafac(tensor_data, rank=rank, normalize_factors=True)
weights, factors = cp_factors
# Tucker分解
ranks = [3, 4, 2] # 各モードのランク
tucker_factors = tucker(tensor_data, ranks=ranks, init='random')
core, factors = tucker_factors
# 因子の可視化(例:第1モード(患者)の因子)
plt.figure(figsize=(12, 6))
for r in range(rank):
plt.subplot(1, rank, r+1)
plt.plot(factors[0][:, r])
plt.title(f'患者因子 {r+1}')
plt.xlabel('患者ID')
plt.ylabel('因子得点')
plt.tight_layout()
plt.show()
5.4 深層学習との関連
線形代数は深層学習の基盤となっており、特に以下のような関連が重要です:
- オートエンコーダ
- 非線形次元削減のためのニューラルネットワークモデル
- 入力を低次元の潜在空間に圧縮し、そこから再構成する
-
線形オートエンコーダはPCAと等価になる
-
行列計算と最適化
- 勾配降下法における行列演算の効率化
- バッチ正規化における共分散行列の計算
- 敵対的生成ネットワーク(GAN)における線形代数の応用
オートエンコーダの実装例:
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
# データの読み込みと前処理
data = np.load('health_monitoring_data.npy')
data_scaled = (data - np.mean(data, axis=0)) / np.std(data, axis=0)
# オートエンコーダの構築
input_dim = data.shape[1]
encoding_dim = 2 # 潜在空間の次元
# エンコーダ
input_layer = Input(shape=(input_dim,))
encoder = Dense(encoding_dim, activation='relu')(input_layer)
# デコーダ
decoder = Dense(input_dim, activation='sigmoid')(encoder)
# オートエンコーダモデル
autoencoder = Model(inputs=input_layer, outputs=decoder)
autoencoder.compile(optimizer=Adam(), loss='mse')
# エンコーダモデル(特徴抽出用)
encoder_model = Model(inputs=input_layer, outputs=encoder)
# モデルの訓練
history = autoencoder.fit(
data_scaled, data_scaled,
epochs=50,
batch_size=32,
shuffle=True,
validation_split=0.2
)
# エンコードされたデータの可視化
encoded_data = encoder_model.predict(data_scaled)
plt.figure(figsize=(10, 8))
plt.scatter(encoded_data[:, 0], encoded_data[:, 1], alpha=0.7)
plt.colorbar()
plt.title('オートエンコーダによる2次元潜在空間')
plt.xlabel('潜在次元1')
plt.ylabel('潜在次元2')
plt.show()
6. 総合演習問題
基本問題(理解度確認)
-
SVD、PCA、因子分析の主な違いを説明し、それぞれがどのような場合に適しているかを述べなさい。
-
画像データに対するSVDの応用について、特異値を削減することでどのような効果が得られるか説明しなさい。
-
以下の3×3行列のSVDを計算し、特異値と特異ベクトルを求めなさい。また、ランク1近似を求めなさい。 \(\(A = \begin{pmatrix} 3 & 1 & 1 \\ 1 & 3 & 1 \\ 1 & 1 & 3 \end{pmatrix}\)\)
-
PCAと非線形次元削減法(t-SNEまたはUMAP)の違いを説明し、それぞれが適している状況について述べなさい。