機械学習のPython実現ガイド

【概要】機械学習の用語(46項目)とPython実装を示す。用語は教師あり学習手法、教師なし学習手法(クラスタリング)、次元削減・特徴抽出手法、行列分解手法、評価指標、実装支援技術、実装結果の検証・評価に分類され、対応するPython関数を明示する。実装例として、ロジスティック回帰、SVM、k-NN、決定木・ランダムフォレスト、k-means、階層的クラスタリング、DBSCAN、PCA、t-SNE、因子分析、線形判別分析(LDA)、特異値分解(SVD)、QR分解の13のプログラムを提供する。

【サイト内のPython関連主要ページ】

【外部リソース】

機械学習の基本

用語リスト

教師あり学習手法

教師なし学習手法(クラスタリング)

次元削減・特徴抽出手法

行列分解手法

評価指標

実装のための技術

実装結果の検証,評価

Python での実現

教師あり学習手法(6項目)
用語 対応関数・クラス・属性
ロジスティック回帰

主要LogisticRegression (scikit-learn) - クラス

関連fit, predict - メソッド

サポートベクターマシン(SVM)

主要SVC (scikit-learn) - クラス(分類用)

関連SVR (scikit-learn) - クラス(回帰用)

k近傍法(k-NN)

主要KNeighborsClassifier (scikit-learn) - クラス(分類用)

関連KNeighborsRegressor (scikit-learn) - クラス(回帰用)

決定木

主要DecisionTreeClassifier (scikit-learn) - クラス(分類用)

関連DecisionTreeRegressor (scikit-learn) - クラス(回帰用)

ランダムフォレスト

主要RandomForestClassifier (scikit-learn) - クラス(分類用)

関連RandomForestRegressor (scikit-learn) - クラス(回帰用)

属性feature_importances_ - 特徴量重要度

線形判別分析(LDA)

主要LinearDiscriminantAnalysis (scikit-learn) - クラス

属性coef_ - 判別係数

属性explained_variance_ratio_ - 各判別関数の寄与率

教師なし学習手法(クラスタリング)(3項目)
用語 対応関数・クラス・属性
k-meansクラスタリング

主要KMeans (scikit-learn) - クラス

属性inertia_ - クラスタ内分散

階層的クラスタリング

主要AgglomerativeClustering (scikit-learn) - クラス(凝集型)

関連linkage (scipy.cluster.hierarchy) - デンドログラム作成用関数

DBSCAN

主要DBSCAN (scikit-learn) - クラス

次元削減・特徴抽出手法(3項目)
用語 対応関数・クラス・属性
PCA(主成分分析)

主要PCA (scikit-learn) - クラス

属性explained_variance_ratio_ - 寄与率

属性explained_variance_ - 固有値

属性components_ - 主成分負荷量

因子分析

主要FactorAnalysis (scikit-learn) - クラス

属性components_ - 因子負荷量

t-SNE

主要TSNE (scikit-learn) - クラス

行列分解手法(2項目)
用語 対応関数・クラス・属性
特異値分解(SVD)

主要np.linalg.svd (numpy) - 関数

関連TruncatedSVD (scikit-learn) - クラス(疎行列対応)

QR分解

主要np.linalg.qr (numpy) - 関数

評価指標(12項目)
用語 対応関数・クラス・属性
精度(Accuracy)

主要accuracy_score (scikit-learn) - 関数

関連classification_report (scikit-learn) - 複数指標を一括出力

適合率(Precision)

主要precision_score (scikit-learn) - 関数

関連classification_report (scikit-learn) - 複数指標を一括出力

再現率(Recall)

主要recall_score (scikit-learn) - 関数

関連classification_report (scikit-learn) - 複数指標を一括出力

F1スコア

主要f1_score (scikit-learn) - 関数

関連classification_report (scikit-learn) - 複数指標を一括出力

コフェネティック相関係数

主要cophenet (scipy.cluster.hierarchy) - 関数

KL-divergence(Kullback-Leibler情報量)

主要entropy (scipy.stats) - 関数(2つの確率分布を引数に指定)

寄与率

主要PCA.explained_variance_ratio_ (scikit-learn) - 属性

累積寄与率

主要cumsum (numpy) - 関数(PCA.explained_variance_ratio_に適用)

固有値

主要PCA.explained_variance_ (scikit-learn) - 属性

主成分負荷量

主要PCA.components_ (scikit-learn) - 属性

共通性

主要FactorAnalysis.components_ (scikit-learn) - 属性(因子負荷量の二乗和で算出)

判別係数

主要LinearDiscriminantAnalysis.coef_ (scikit-learn) - 属性

実装のための技術(8項目)
用語 対応関数・クラス・属性
標準化

主要StandardScaler (scikit-learn) - クラス

関連fit_transform - メソッド

次元削減

主要PCA (scikit-learn) - クラス

関連TSNE (scikit-learn) - クラス

k分割交差検証

主要cross_val_score (scikit-learn) - 関数

関連KFold (scikit-learn) - クラス(分割方法の指定)

グリッドサーチ

主要GridSearchCV (scikit-learn) - クラス

関連RandomizedSearchCV (scikit-learn) - クラス(ランダム探索用)

データの可視化

主要scatter (matplotlib.pyplot) - 関数(散布図)

関連plot (matplotlib.pyplot) - 関数(折れ線グラフ)

関連heatmap (seaborn) - 関数(ヒートマップ)

エルボー法

主要KMeans.inertia_ (scikit-learn) - 属性

関連plot (matplotlib.pyplot) - プロット用関数

デンドログラム

主要dendrogram (scipy.cluster.hierarchy) - 関数

関連linkage (scipy.cluster.hierarchy) - リンケージ行列作成用関数

最尤推定

主要LogisticRegression (scikit-learn) - クラス(内部で使用)

関連FactorAnalysis (scikit-learn) - クラス(内部で使用)

実装結果の検証,評価(4項目)
用語 対応関数・クラス・属性
汎化性能

主要cross_val_score (scikit-learn) - 関数

ハイパーパラメータ

主要GridSearchCV (scikit-learn) - クラス(最適化用)

関連RandomizedSearchCV (scikit-learn) - クラス(ランダム探索用)

混同行列(Confusion Matrix)

主要confusion_matrix (scikit-learn) - 関数

関連classification_report (scikit-learn) - 関数(混同行列から派生する指標を一括出力)

関連ConfusionMatrixDisplay (scikit-learn) - クラス(可視化用)

シルエット係数(Silhouette Coefficient)

主要silhouette_score (scikit-learn) - 関数(全体スコア)

関連silhouette_samples (scikit-learn) - 関数(サンプル毎の係数)

データ準備(前提となる処理)
用語 対応関数・クラス・属性
データ分割

主要train_test_split (scikit-learn) - 関数

データフレーム操作

主要DataFrame (pandas) - クラス

補足:classification_reportについて
classification_report (scikit-learn)は、精度(Accuracy)、適合率(Precision)、再現率(Recall)、F1スコアの4つの評価指標を一括で計算・出力する関数である。個別の指標を計算する場合は各関数(accuracy_score等)を使用し、まとめて結果を確認したい場合はclassification_reportを使用する。

Pythonプログラム例

1. ロジスティック回帰


from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix

# データ準備
iris = load_iris()
X = iris.data
y = iris.target

# 学習データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# ロジスティック回帰モデルの構築と学習
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)

# テストデータでの予測と性能評価
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred))

# 混同行列の表示
print("Confusion Matrix:")
print(confusion_matrix(y_test, y_pred))

# 5分割交差検証による性能評価
cv_scores = cross_val_score(model, X, y, cv=5)
print(f"Cross-validation scores: {cv_scores}")
print(f"Average CV score: {cv_scores.mean():.3f} (+/- {cv_scores.std() * 2:.3f})")

線形モデルとシグモイド関数を組み合わせた分類手法を実装する。データセットを訓練データとテストデータに分割し、ロジスティック回帰モデルを構築する。最尤推定により重みパラメータを最適化し、テストデータで予測を行う。分類レポートにより精度、適合率、再現率、F1スコアを算出する。混同行列により予測結果を真陽性、偽陽性、真陰性、偽陰性の4つに分類し、表形式で示す。k分割交差検証により汎化性能を評価し、各分割での評価指標の平均と標準偏差からモデルの安定性を確認する。多クラス分類にはソフトマックス関数が内部で適用される。

2. SVM


import pandas as pd
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import classification_report

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデル構築
svm = SVC(kernel='rbf', random_state=42)

# パラメータグリッド
param_grid = {
    'C': [0.1, 1, 10],
    'gamma': ['scale', 'auto', 0.1, 1],
}

# グリッドサーチ
grid_search = GridSearchCV(
    svm,
    param_grid,
    cv=5,
    scoring='accuracy',
    n_jobs=-1
)

# モデル学習
grid_search.fit(X_train, y_train)

# 最適パラメータと評価
print(f"Best parameters: {grid_search.best_params_}")
y_pred = grid_search.predict(X_test)
print(classification_report(y_test, y_pred))

データを高次元空間に写像し、マージン最大化により最適な分離超平面を探索する。RBFカーネルを使用し、カーネルトリックにより非線形分類を実現する。グリッドサーチによりハイパーパラメータ(正則化係数Cとカーネルパラメータgamma)の全組み合わせを探索し、k分割交差検証により最適値を決定する。並列処理により計算を高速化し、最適パラメータでモデルを構築する。テストデータで予測を行い、分類レポートにより精度、適合率、再現率、F1スコアを算出する。距離や内積を用いるため、特徴量の標準化が推奨される。

3. k-NN


import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.metrics import classification_report

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# k値の範囲でモデル評価
k_range = range(1, 31)
k_scores = []
for k in k_range:
    knn = KNeighborsClassifier(n_neighbors=k)
    scores = cross_val_score(knn, X, y, cv=5)
    k_scores.append(scores.mean())

# 最適なkの選択
best_k = k_range[np.argmax(k_scores)]
print(f"Best k: {best_k}")

# 最適モデルの構築と評価
knn = KNeighborsClassifier(n_neighbors=best_k)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print(classification_report(y_test, y_pred))

新規データポイントに対し、訓練データセットからk個の最近傍点を距離計算により特定し、その近傍点の値に基づいて予測を行うインスタンスベース学習手法を実装する。k値を1から30の範囲で変化させ、各k値についてk分割交差検証により汎化性能を評価する。評価指標の平均が最大となるk値を最適値として選択する。最適なk値でモデルを構築し、テストデータで予測を行う。分類レポートにより精度、適合率、再現率、F1スコアを算出する。距離ベースのアルゴリズムであるため、特徴量の標準化が推奨される。

4. 決定木・ランダムフォレスト


import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import classification_report

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# 学習用とテスト用にデータを分割
X_train, X_test, y_train, y_test = train_test_split(
   X, y, test_size=0.3, random_state=42
)

# 決定木による学習と予測
dt = DecisionTreeClassifier(random_state=42)
dt.fit(X_train, y_train)
dt_pred = dt.predict(X_test)
print("Decision Tree:")
print(classification_report(y_test, dt_pred))

# ランダムフォレストによる学習と予測
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
rf_pred = rf.predict(X_test)
print("\nRandom Forest:")
print(classification_report(y_test, rf_pred))

# 特徴量重要度の算出と表示
feature_importance = pd.DataFrame({
   'feature': iris.feature_names,
   'importance': rf.feature_importances_
})
print("\nFeature importance:")
print(feature_importance.sort_values('importance', ascending=False))

決定木は特徴量に基づく階層的な木構造により、データを再帰的に分割して判断ルールを生成する手法である。ランダムフォレストは複数の決定木を組み合わせたアンサンブル学習手法であり、各決定木の予測結果を統合することで高い精度と汎化性能を実現する。データセットを訓練データとテストデータに分割し、両手法でモデルを構築する。分類レポートにより各手法の性能を評価する。特徴量重要度により各特徴量がモデルの予測に寄与する程度を定量的に評価する。スケーリングや前処理の要件が最小限である。

5. k-means


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.datasets import load_iris

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# エルボー法とシルエット分析による最適クラスタ数の決定
inertias = []
silhouette_scores = []
K = range(2, 10)

# 各クラスタ数での評価指標を計算
for k in K:
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(X)
    inertias.append(kmeans.inertia_)
    silhouette_scores.append(silhouette_score(X, kmeans.labels_))

# エルボー法のプロット
plt.figure(figsize=(8, 6))
plt.plot(K, inertias, 'bo-')
plt.xlabel('Number of clusters (k)')
plt.ylabel('Inertia')
plt.title('Elbow Method')
plt.grid(True)
plt.show()

# シルエットスコアが最大となるクラスタ数を選択
best_k = K[np.argmax(silhouette_scores)]

# 最適なクラスタ数でモデルを再学習
kmeans = KMeans(n_clusters=best_k, random_state=42)
clusters = kmeans.fit_predict(X)

# 結果の出力
print(f"Best number of clusters: {best_k}")
print(f"Silhouette score: {silhouette_score(X, clusters):.3f}")

# クラスタリング結果の基本統計量
cluster_stats = pd.DataFrame(X)
cluster_stats['Cluster'] = clusters
print("\nCluster statistics:")
print(cluster_stats.groupby('Cluster').mean())

クラスタ中心の初期配置、データポイントの割り当て、中心の再計算を反復する教師なし学習アルゴリズムを実装する。クラスタ数を2から9の範囲で変化させ、各クラスタ数についてクラスタ内分散とシルエット係数を計算する。エルボー法によりクラスタ数kとクラスタ内分散の関係をプロットし、クラスタ内分散の減少が急激から緩やかに変わる転換点から最適なクラスタ数を決定する。シルエット係数により同一クラスタ内の凝集度と他クラスタとの分離度を評価する。シルエット係数が最大となるクラスタ数でモデルを再学習し、クラスタごとの基本統計量を算出する。

6. 階層的クラスタリング


import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage, cophenet
from scipy.spatial.distance import pdist
import matplotlib.pyplot as plt

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# 階層的クラスタリング実行
hierarchical = AgglomerativeClustering(n_clusters=3)
clusters = hierarchical.fit_predict(X)

# 結果の表示
print("階層的クラスタリング結果:")
print("各クラスタのサンプル数:", np.bincount(clusters))

# クラスタごとの基本統計量
cluster_stats = pd.DataFrame(X)
cluster_stats['Cluster'] = clusters
print("\nクラスタごとの平均値:")
print(cluster_stats.groupby('Cluster').mean())

# デンドログラム作成
linkage_matrix = linkage(X, method='ward')
plt.figure(figsize=(10, 7))
dendrogram(linkage_matrix)
plt.title('Hierarchical Clustering Dendrogram')
plt.xlabel('Sample index')
plt.ylabel('Distance')
plt.show()

# コフェネティック相関係数の計算
c, coph_dists = cophenet(linkage_matrix, pdist(X))
print(f"\nCophenetic correlation coefficient: {c:.3f}")

データの階層構造を抽出する手法を実装する。ボトムアップ(凝集型)アプローチにより、個別データ点から開始して近接クラスタを段階的に統合する。ウォード法による距離計算により、クラスタ内分散を最小化する方向で統合を進める。クラスタ数を3に設定し、階層的クラスタリングを実行する。各クラスタのサンプル数とクラスタごとの平均値を表示し、クラスタの特性を把握する。デンドログラムにより階層構造を樹形図として可視化し、データポイント間の距離関係と各段階での統合距離を表現する。コフェネティック相関係数により元の距離とデンドログラム上の距離の相関を測定し、階層的クラスタリングの結果を評価する。

7. DBSCAN


import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# データの標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# DBSCANによるクラスタリング
dbscan = DBSCAN(eps=0.3, min_samples=5)
clusters = dbscan.fit_predict(X_scaled)

# クラスタ評価
n_clusters = len(set(clusters)) - (1 if -1 in clusters else 0)

# シルエットスコアの計算
if n_clusters >= 2 and len(clusters[clusters != -1]) >= 2:
    mask = clusters != -1
    silhouette_avg = silhouette_score(X_scaled[mask], clusters[mask])
    print(f"Number of clusters: {n_clusters}")
    print(f"Silhouette score: {silhouette_avg:.3f}")
else:
    print(f"Number of clusters: {n_clusters}")
    print("Silhouette score cannot be calculated.")

密度ベースでクラスタリングを行うアルゴリズムを実装する。データを標準化により前処理し、特徴量間のスケールを統一する。データ点を、十分に密な領域にあるコアポイント、コアポイントの近傍にある境界ポイント、どのクラスタにも属さないノイズポイントの3種類に分類する。パラメータepsにより近傍を定義する距離閾値を、min_samplesによりコアポイント判定の最小サンプル数を設定する。クラスタ数の事前指定が不要で、外れ値の自動識別が可能である。ノイズポイントを除外してクラスタ数を計算し、シルエット係数によりクラスタリング結果の品質を評価する。

8. PCA


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# データの標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# PCAの実行
pca = PCA()
X_pca = pca.fit_transform(X_scaled)

# 寄与率、累積寄与率、固有値の表示
explained_variance_ratio = pca.explained_variance_ratio_
cumulative_variance_ratio = np.cumsum(explained_variance_ratio)
eigenvalues = pca.explained_variance_

print("Explained variance ratio:", explained_variance_ratio)
print("Cumulative explained variance ratio:", cumulative_variance_ratio)
print("Eigenvalues:", eigenvalues)

# 主成分負荷量の表示
print("\n主成分負荷量:")
for i, loadings in enumerate(pca.components_, 1):
    print(f"\n第{i}主成分:")
    for j, loading in enumerate(loadings):
        print(f"  {iris.feature_names[j]}: {loading:.4f}")

# 可視化
plt.figure(figsize=(12, 4))

# スクリープロット
plt.subplot(131)
plt.plot(range(1, len(explained_variance_ratio) + 1), explained_variance_ratio, 'bo-')
plt.xlabel('Principal Component')
plt.ylabel('Explained Variance Ratio')
plt.title('Scree Plot')
plt.grid(True)

# 累積寄与率のプロット
plt.subplot(132)
plt.plot(range(1, len(cumulative_variance_ratio) + 1), cumulative_variance_ratio, 'ro-')
plt.xlabel('Number of Components')
plt.ylabel('Cumulative Explained Variance Ratio')
plt.title('Cumulative Variance')
plt.grid(True)

# 第1・第2主成分でのデータ分布
plt.subplot(133)
scatter = plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis')
plt.xlabel('First Principal Component')
plt.ylabel('Second Principal Component')
plt.title('Data Distribution in PC Space')
plt.colorbar(scatter)

plt.tight_layout()
plt.show()

データの分散が最大となる軸を算出し、次元削減を実現する統計的手法を実装する。データを標準化により前処理し、特徴量間のスケールを統一する。PCAを実行し、元のデータを主成分空間に変換する。寄与率により各主成分が全体の分散を説明する割合を算出する。累積寄与率により複数の主成分による累積的な分散説明率を計算し、次元削減における情報保持率を評価する。固有値により各主成分が持つ分散の大きさを表し、主成分の重要度を示す主成分負荷量により各主成分と元の変数との相関を示し、主成分の解釈を可能にする。スクリープロットにより主成分の重要度を可視化し、寄与率の減少傾向を確認する。第1・第2主成分空間でのデータ分布を散布図により可視化し、クラスタ構造を把握する。

9. t-SNE


import pandas as pd
from sklearn.datasets import load_iris
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# t-SNEの実行
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
X_tsne = tsne.fit_transform(X)

# 結果の可視化
plt.figure(figsize=(10, 6))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap='viridis')
plt.colorbar(scatter)
plt.title('t-SNE visualization of Iris dataset')
plt.xlabel('First t-SNE component')
plt.ylabel('Second t-SNE component')
plt.show()

確率分布の一致度を最適化する非線形次元削減手法を実装する。近傍点間の関係(局所構造)を保持しながら、反復的な最適化プロセスによりクラスタ構造の可視化に優れた低次元表現を生成する。高次元空間と低次元空間における点間の類似度を表す確率分布を定義し、KL-divergenceによりその一致度を評価しながら最適化を行う。パラメータperplexityにより近傍点の数を制御し、データの局所構造と大域構造のバランスを調整する。2次元に次元削減し、散布図により可視化する。色分けによりクラスタ構造を視覚的に確認できる。

10. 因子分析


import numpy as np
from sklearn.decomposition import FactorAnalysis
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import pandas as pd

# Irisデータセットの読み込み
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

# データの標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 因子分析の実行
fa = FactorAnalysis(n_components=2, random_state=42)
X_fa = fa.fit_transform(X_scaled)

# 因子負荷量の表示
print("因子負荷量:")
for i, feature_name in enumerate(iris.feature_names):
    print(f"\n{feature_name}:")
    for j, loading in enumerate(fa.components_[:, i], 1):
        print(f"  因子{j}: {loading:.4f}")

# 共通性の計算
communalities = np.sum(fa.components_**2, axis=0)
print("\n共通性:")
for i, (feature_name, comm) in enumerate(zip(iris.feature_names, communalities)):
    print(f"{feature_name}: {comm:.4f}")

# 因子間相関の計算
factor_corr = np.corrcoef(X_fa.T)
print("\n因子間相関:")
print(factor_corr)

# 可視化
plt.figure(figsize=(12, 4))

# 因子負荷量のプロット
plt.subplot(131)
plt.scatter(fa.components_[0], fa.components_[1])
for i, feature_name in enumerate(iris.feature_names):
    plt.annotate(feature_name, (fa.components_[0, i], fa.components_[1, i]))
plt.xlabel('第1因子')
plt.ylabel('第2因子')
plt.title('因子負荷量プロット')
plt.grid(True)
plt.axhline(y=0, color='k', linestyle='--', alpha=0.3)
plt.axvline(x=0, color='k', linestyle='--', alpha=0.3)

# 因子得点の分布
plt.subplot(132)
scatter = plt.scatter(X_fa[:, 0], X_fa[:, 1], c=y, cmap='viridis', alpha=0.6)
plt.xlabel('第1因子得点')
plt.ylabel('第2因子得点')
plt.title('因子得点の分布')
plt.colorbar(scatter)

# 共通性の棒グラフ
plt.subplot(133)
plt.bar(range(len(communalities)), communalities)
plt.xticks(range(len(iris.feature_names)), iris.feature_names, rotation=45, ha='right')
plt.ylabel('共通性')
plt.title('各変数の共通性')
plt.grid(True, axis='y')

plt.tight_layout()
plt.show()

観測変数の背後にある潜在的な共通因子を抽出する統計的手法を実装する。データを標準化により前処理し、特徴量間のスケールを統一する。因子分析を実行し、2つの潜在因子を抽出する。因子負荷量により各観測変数と潜在因子との関係を定量化する。共通性により各観測変数が共通因子によって説明される分散の割合を算出する。因子間相関により抽出された因子間の関係を評価する。因子負荷量プロットにより各変数がどの因子に強く関連するかを視覚的に把握する。因子得点の分布により、データが因子空間でどのように配置されるかを確認する。PCAがデータの分散を最大化する軸を探索するのに対し、因子分析は観測変数間の相関構造を説明する潜在因子を仮定する点で異なる。

11. 線形判別分析(LDA)


import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt

# Irisデータセットの読み込み
iris = load_iris()
X = iris.data
y = iris.target

# データの標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# データの分割
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.3, random_state=42
)

# LDAの実行
lda = LinearDiscriminantAnalysis()
X_lda = lda.fit_transform(X_scaled, y)

# 判別係数の表示
print("判別係数:")
for i, coef in enumerate(lda.coef_, 1):
    print(f"\n判別関数{i}:")
    for j, (feature_name, c) in enumerate(zip(iris.feature_names, coef)):
        print(f"  {feature_name}: {c:.4f}")

# 分類性能の評価
y_pred = lda.predict(X_test)
print("\n分類性能:")
print(f"正答率: {lda.score(X_test, y_test):.4f}")
print("\n分類レポート:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

# 各判別関数の寄与率
print("\n各判別関数の寄与率:")
explained_ratios = lda.explained_variance_ratio_
for i, ratio in enumerate(explained_ratios, 1):
    print(f"判別関数{i}: {ratio:.4f}")

# 可視化
plt.figure(figsize=(12, 4))

# 第1・第2判別関数でのデータ分布
plt.subplot(131)
scatter = plt.scatter(X_lda[:, 0], X_lda[:, 1], c=y, cmap='viridis')
plt.xlabel('第1判別関数')
plt.ylabel('第2判別関数')
plt.title('判別空間でのデータ分布')
plt.colorbar(scatter, ticks=[0, 1, 2], label='Class')

# 判別関数の寄与率
plt.subplot(132)
plt.bar(range(1, len(explained_ratios) + 1), explained_ratios)
plt.xlabel('判別関数')
plt.ylabel('寄与率')
plt.title('判別関数の寄与率')
plt.grid(True, axis='y')

# 第1判別関数のヒストグラム
plt.subplot(133)
for class_label in np.unique(y):
    plt.hist(X_lda[y == class_label, 0], alpha=0.5,
             label=iris.target_names[class_label], bins=20)
plt.xlabel('第1判別関数')
plt.ylabel('頻度')
plt.title('第1判別関数によるクラス分離')
plt.legend()
plt.grid(True, axis='y')

plt.tight_layout()
plt.show()

教師あり学習における次元削減手法を実装する。クラス間の分散を最大化し、クラス内の分散を最小化する軸を見つけることで、特徴抽出を実現する。データを標準化により前処理し、特徴量間のスケールを統一する。LDAを実行し、3クラス問題に対して2つの判別軸を抽出する。判別係数により各判別関数における特徴量の寄与を定量化する。分類性能を評価し、正答率と分類レポートを表示する。各判別関数の寄与率により、クラス分離への寄与度を把握する。判別空間でのデータ分布を可視化し、クラス分離の状況を確認する。第1判別関数のヒストグラムにより、各クラスがどの程度分離されているかを視覚的に把握する。PCAが教師なし次元削減であるのに対し、LDAはクラスラベル情報を活用する教師あり次元削減である点で異なる。

12. 特異値分解(SVD)


import numpy as np
import matplotlib.pyplot as plt

# サンプルデータの生成
np.random.seed(42)
n_rows, n_cols = 100, 50

# ランク3の行列を生成
U_true = np.random.normal(0, 1, (n_rows, 3))
V_true = np.random.normal(0, 1, (n_cols, 3))
singular_values_true = np.array([10, 5, 2])

X = U_true @ np.diag(singular_values_true) @ V_true.T

# ノイズを追加
X_noisy = X + np.random.normal(0, 0.1, (n_rows, n_cols))

# SVDの実行
U, s, Vt = np.linalg.svd(X_noisy, full_matrices=False)

# 特異値の表示
print("特異値(上位10個):")
for i, value in enumerate(s[:10], 1):
    print(f"σ_{i}: {value:.4f}")

# 累積寄与率の計算
cumulative_variance = np.cumsum(s**2) / np.sum(s**2)
print(f"\n上位3成分の累積寄与率: {cumulative_variance[2]:.4f}")

# 低ランク近似の誤差を計算
errors = []
ranks = range(1, min(n_rows, n_cols) + 1)

for r in ranks:
    X_approx = U[:, :r] @ np.diag(s[:r]) @ Vt[:r, :]
    error = np.linalg.norm(X_noisy - X_approx, 'fro')
    errors.append(error)

# 可視化
plt.figure(figsize=(15, 4))

# 特異値のプロット
plt.subplot(141)
plt.plot(range(1, len(s) + 1), s, 'o-')
plt.yscale('log')
plt.xlabel('成分番号')
plt.ylabel('特異値')
plt.title('特異値のスケープロット')
plt.grid(True)

# 累積寄与率
plt.subplot(142)
plt.plot(range(1, len(s) + 1), cumulative_variance, 'o-')
plt.xlabel('成分数')
plt.ylabel('累積寄与率')
plt.title('累積寄与率')
plt.grid(True)

# 近似誤差
plt.subplot(143)
plt.plot(ranks[:20], errors[:20], 'o-')
plt.xlabel('使用する特異値の数')
plt.ylabel('近似誤差')
plt.title('低ランク近似の誤差')
plt.grid(True)

# オリジナルデータの可視化
plt.subplot(144)
plt.imshow(X_noisy[:20, :20], cmap='coolwarm', aspect='auto')
plt.title('オリジナルデータ(部分)')
plt.colorbar()

plt.tight_layout()
plt.show()

# 低ランク近似の比較
plt.figure(figsize=(15, 4))
ranks_demo = [1, 3, 10]

for i, r in enumerate(ranks_demo):
    X_approx = U[:, :r] @ np.diag(s[:r]) @ Vt[:r, :]
    plt.subplot(1, len(ranks_demo), i+1)
    plt.imshow(X_approx[:20, :20], cmap='coolwarm', aspect='auto')
    plt.title(f'ランク{r}での近似')
    plt.colorbar()

plt.tight_layout()
plt.show()

行列を3つの行列(U、Σ、V^T)の積に分解する手法を実装する。ランク3の行列にノイズを加えたデータを生成し、SVDを実行する。特異値により各成分の重要度を定量化する。累積寄与率により、上位成分がデータの分散をどの程度説明するかを評価する。低ランク近似により、小さい特異値を無視してデータを圧縮する。近似誤差をプロットし、使用する特異値の数と再構成精度の関係を可視化する。特異値のスケープロットにより、重要な成分の数を判断する。異なるランクでの近似結果を比較し、データ圧縮の効果を視覚的に確認する。SVDはPCAの基礎となる手法であり、データ圧縮や潜在的意味解析などの応用が可能である。

13. QR分解


import numpy as np
import matplotlib.pyplot as plt

# サンプルデータの生成
np.random.seed(42)
n_rows, n_cols = 5, 3
A = np.random.randn(n_rows, n_cols)

# QR分解の実行
Q, R = np.linalg.qr(A)

# 結果の表示
print("元の行列 A:")
print(A)
print("\nQ行列(直交行列):")
print(Q)
print("\nR行列(上三角行列):")
print(R)

# 検証
print("\n検証結果:")
print("Q^T Q(単位行列に近いことを確認):")
print(np.round(Q.T @ Q, decimals=10))
print("\nQR(元の行列Aに近いことを確認):")
reconstruction_error = np.linalg.norm(A - Q @ R)
print(f"再構成誤差: {reconstruction_error:.10f}")

# 可視化
plt.figure(figsize=(15, 4))

# 元の行列の可視化
plt.subplot(141)
plt.imshow(A, cmap='coolwarm', aspect='auto')
plt.title('元の行列 A')
plt.colorbar()

# Q行列の可視化
plt.subplot(142)
plt.imshow(Q, cmap='coolwarm', aspect='auto')
plt.title('直交行列 Q')
plt.colorbar()

# R行列の可視化
plt.subplot(143)
plt.imshow(R, cmap='coolwarm', aspect='auto')
plt.title('上三角行列 R')
plt.colorbar()

# Q^T Q の可視化
plt.subplot(144)
plt.imshow(Q.T @ Q, cmap='coolwarm', aspect='auto')
plt.title('Q^T Q(単位行列)')
plt.colorbar()

plt.tight_layout()
plt.show()

# QR分解の応用:最小二乗法による線形回帰
print("\n\nQR分解の応用:最小二乗法による線形回帰")

# サンプルデータの生成
n_samples = 100
X_data = np.random.uniform(0, 10, n_samples)
y_data = 2 * X_data + 1 + np.random.normal(0, 1, n_samples)

# 設計行列の作成
A_reg = np.vstack([X_data, np.ones(n_samples)]).T

# QR分解を使用した最小二乗法
Q_reg, R_reg = np.linalg.qr(A_reg)
beta = np.linalg.solve(R_reg, Q_reg.T @ y_data)

print(f"\n推定された傾き: {beta[0]:.4f}")
print(f"推定された切片: {beta[1]:.4f}")

# 結果の可視化
plt.figure(figsize=(8, 6))
plt.scatter(X_data, y_data, alpha=0.5, label='データ点')
X_sort = np.sort(X_data)
plt.plot(X_sort, beta[0] * X_sort + beta[1], 'r-', linewidth=2,
         label='QR分解による回帰直線')
plt.plot(X_sort, 2 * X_sort + 1, 'g--', linewidth=2,
         label='真の関係')
plt.xlabel('X')
plt.ylabel('y')
plt.title('QR分解を用いた線形回帰')
plt.legend()
plt.grid(True)
plt.show()

行列を直交行列Q(Q^T Q = I)と上三角行列Rの積に分解する手法を実装する。ランダムに生成した行列に対してQR分解を実行する。Q行列が直交行列であることを、Q^T Qが単位行列に近いことで検証する。QRの積が元の行列Aを再構成できることを、フロベニウスノルムにより確認する。各行列を可視化し、QR分解の構造を視覚的に把握する。QR分解の応用として、最小二乗法による線形回帰問題を実装する。設計行列を作成し、QR分解を用いて回帰係数を安定的に求める。推定された回帰直線と真の関係を比較し、QR分解による解法の有効性を確認する。QR分解はGram-Schmidt直交化法の実装として解釈でき、最小二乗法や固有値計算において重要な役割を持つ。