ぱと隊長日誌

ブログ運用もエンジニアとしての生き方も模索中

「化学のためのPythonによるデータ解析・機械学習入門(改訂2版)」略語集

化学のためのPythonによるデータ解析・機械学習入門(改訂2版)」は略語が頻出します。そこで、繰り返し登場する略語について一覧にまとめました。スムーズに読み進めるためのお役に立てば幸いです。

なお、本記事の内容は(改訂2版)を基準としていますが、初版でも活用できると思われます。

用語の説明は可能な限り同書を参考にしましたが、まとめが難しかったケースではAIで生成しています。その場合、"(AI)"と記載しています。

並び順はページ数を基準としています。

略称  英語  日本語  説明 ページ
PCA  Principal Component Analysis  主成分分析  多数の特徴量を、主成分軸上に投影したデータの分散が最大になるように主成分軸の方向を順に決め、少数の互いに直交する軸へ変換する手法です。これにより、情報の損失を抑えながらデータを低次元化し、サンプル間の関係を可視化できます。(AI)  26
t-SNE t-distributed Stochastic Neighbor Embedding    t-SNEとは、高次元空間におけるサンプル間の類似度を同時確率分布で表し、その分布と低次元空間における類似度の分布との差が小さくなるようにサンプルを配置する次元削減手法です。低次元空間ではスチューデントの t 分布を用いることで、近いサンプル同士を近く、異なる集団を離して可視化しやすくします。(AI)  43
OLS  (MLR) Ordinary Least Squares  (Multiple Linear Regression)  最小二乗法による線形重回帰分析  目的変数を複数の説明変数の線形結合で表し、実測値と推定値との差である残差の二乗和が最小となるように各説明変数の回帰係数を決定する手法です。(AI)  53
MAE Mean Absolute Error    誤差の絶対値の平均値。  58
RMSE Root-Mean-Squared Error    誤差を2乗して平均値を計算し1/2乗したもの。  58
PCR Principal Component Regression  主成分回帰  説明変数を選択せずに、PCAで説明変数を互いに無相関な主成分に変換してから、主成分と目的変数との間でOLSを行うこと。  61
CV Cross Validation  クロスバリデーション  データを複数のグループに分け、一部を学習用、残りを検証用として交代で用いることで、未知のデータに対するモデルの予測性能を評価する方法です。複数回の評価結果をまとめることで、特定のデータ分割に左右されにくい性能評価ができます。(AI)  62
PLS Partial Least Squares  部分的最小二乗法  主成分間の無相関性を維持しながら目的変数の情報を考慮して主成分を計算し、主成分と目的変数との間で回帰モデルを構築する手法の1つ。目的変数と主成分との間の共分散が最大になるように主成分軸の方向が決められます。  64
SVR Support Vector Regression  サポートベクター回帰  SVMを回帰分析に応用した手法で、基本的にはOLS,PCR,PLSのような線形の回帰分析手法ですが、カーネルトリックという手法により非線形手法に拡張できます。  70
DCV Double Cross-Validation  ダブルクロスバリデーション  外側のCVで分けたトレーニングデータに対して内側のCVを行い、ハイパーパラメータを最適化した後、その条件で構築したモデルを外側のテストデータに適用することで、モデルの予測性能をより適切に評価する方法です。(AI)  80
k-NN k-Nearst Neighbors algorithm  k近傍法  あるサンプルのクラスを推定するときに、クラスがすでにわかっているサンプルの中から、クラスを推定したいサンプルに最も近いk個のサンプルを選び、それらのクラスで多数決をとってクラスを決定する方法です。  82, 102 
SVM Support Vector Machine  サポートベクターマシン  SVRの基になった手法であり、2つのクラスを分類します。  87
DT Decision Tree  決定木  説明変数に対する条件でサンプルを順に分割し、各ノードに含まれるサンプルのクラスができるだけ偏るように分岐条件を決め、終端ノードに到達したサンプルのクラスを推定する分類手法です。(AI)  93
RF Random Forests  ランダムフォレスト  DTモデルをたくさんつくり、新しいサンプルにおけるクラスの推定結果を、各DTモデルの推定結果を多数決することで決めます。  96
AD Applicability Domain  モデルの適用範囲  回帰モデルやクラス分類モデルが本来の推定性能、つまりモデルを構築するときに用いたデータセットに対して示す性能、を発揮できる説明変数のデータ領域のこと。  99
OCSVM One-Class Support Vector Machine    主に正常とみなされるトレーニングサンプルの分布を学習し、カーネル関数を用いてサンプルが密集する領域を囲む境界を求める手法です。新しいサンプルがその領域の内側にあれば既知のデータ分布に近いサンプル、外側にあれば外れサンプルとして判定できるため、異常検知やモデルの適用範囲(AD)の評価に用いられます。  103

PostgreSQL の track_io_timing とパフォーマンス影響

概要

PostgreSQL の track_io_timing はデータベースによる I/O 待機の記録を有効にし、各種統計(pg_stat_* 系)や EXPLAIN などで参照できるようにする設定です。ですが、プラットフォームによっては深刻な負荷の原因になるとし、デフォルトでは無効となっています。

pgsql-hackers でもデフォルトで有効にすることが議論されましたが、プラットフォーム依存のオーバーヘッド懸念が指摘され、少なくとも当該スレッドではデフォルト変更に至っていません。
PostgreSQL: track_io_timing default setting

そこで、track_io_timing がパフォーマンスにどれほど影響を与えるのか、Hyper-V 上の Rocky Linux + PostgreSQL 18.2 で測定した一例を示します。

検証環境

Windows 11 マシンの Hyper-V 環境で検証しました。

ホスト

プロセッサ Intel Core i5-14500
メモリー 32 GB
OS Windows 11 Pro 25H2

Hyper-V

プロセッサ 10個の仮想プロセッサ
メモリー 8 GB
OS Rocky Linux release 9.7
DB PostgreSQL 18.2

検証

検証方針

track_io_timing パラメータの説明を抜粋します。

データベースによるI/O待機の記録を有効にします。 このパラメータはデフォルトで無効になっています。その理由は、現時点の時刻をオペレーティングシステムに繰り返し問い合わせるので、プラットフォームによっては深刻な負荷の原因になるからです。使用しているシステムにおける記録の負荷を計測するためpg_test_timingツールが使用できます。

19.9. 実行時統計情報

また、pg_test_timing の説明では、時間計測のオーバーヘッドやクロックソースによる影響が示されています。
pg_test_timing

これらを踏まえ、以下のように検証を進めることにします。

まずは利用可能なクロックソース毎に pg_test_timing で時間計測のオーバーヘッドを測定します。そして、最良と思われるクロックソースを選択します。

次に track_io_timing パラメータのパフォーマンス影響を計測します。ベンチマークとして pgbench の組み込みスクリプトである tpcb-like, select-only を用います。

クロックソース評価

# cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hyperv_clocksource_tsc_page hyperv_clocksource_msr acpi_pm

-- クロックソースを tsc に変更する場合
# echo tsc > /sys/devices/system/clocksource/clocksource0/current_clocksource

# taskset -c 0 /usr/pgsql-18/bin/pg_test_timing -d 10

「オーバーヘッド込みのループ時間毎」の結果をクロックソース毎に示します。なお、ヒストグラムは割愛していますが、妥当なバラツキと判断しました。

クロックソース ループ時間
tsc 15.29 ns
hyperv_clocksource_tsc_page 16.91 ns
hyperv_clocksource_msr 519.59 ns
acpi_pm 505.39 ns

この結果を受けて、今回は "tsc" を採用することにしました。OSインストール直後のデフォルト設定であること、かつ測定結果が良好であったことを重視しました。

track_io_timing とベンチマーク

$ createdb bench

$ pgbench -i -s 1000 bench

-- track_io_timing 変更後はデータベースを再起動した
# systemctl restart postgresql-18

-- select-only
$ pgbench -S -c 8 -j 8 -T 300 bench

-- tpcb-like
$ pgbench -c 8 -j 8 -T 300 bench

各条件で 3 回計測し、"latency average" の中央値を採用します。結果を以下に示します。

track_io_timing select-only tpcb-like
off 0.385 ms 3.958 ms
on 0.402 ms 3.913 ms

select-only では track_io_timing の有効化で latency が 4.4 % 悪化しました。

一方、tpcb-like は 1.1 % 改善しましたが、差は小さいため、今回の条件では「有意差」と断定せず参考値として扱います。

まとめ

今回の検証シナリオだけ見る限り、良い性能のクロックソースであれば、track_io_timing 有効化の影響は限定的といえそうです。有効化によるパフォーマンス影響を否定できず、通常時の適用は難しくとも、検証のために限定的に利用することは検討の余地があります。

ですが、track_io_timing を有効化したい場面は I/O 負荷を疑っている状況と推測され、調査のための有効化は状況をさらに悪化させる可能性があります。有効化の前に最低限でも pg_test_timing でクロックソースを評価すること。そして、可能であれば事前検証とリカバリー計画を用意した上で適用するのが望ましいと考えます。

PostgreSQLのfillfactorとパフォーマンス検証

概要

PostgreSQL には HOT (Heap-Only Tuples) という、更新のオーバーヘッドを減らす仕組みがあります。詳細は下記の記事を参照ください。
HOTの活用 | Let's POSTGRES

HOT 更新には条件があり、その一つが「HOT更新のための十分なページ領域」です。テーブルの fillfactor(以下、FF)を下げると、ページ内に空き領域を残しやすくなり、HOT 更新が発生しやすくなります。

テーブルのfillfactorを減らすことで、HOT更新のための十分なページ領域の可能性を高めることができます。 そうしない場合でも、HOT更新は発生します。 なぜなら、新しい行は新しいページや、新しい行バージョンのために十分な空き領域を持つ既存のページに自然に移動するからです。

66.7. ヒープ専用タプル(HOT)

PostgreSQL 18 時点で、テーブルの fillfactor のデフォルトは100(可能な限りページを詰める)です。

また、次のような記載もあります。

一般的には、FILLFACTOR=90でHOTが十分に機能するでしょう。

なお、FILLFACTORを設定すると空き領域をテーブルデータ内に作ることになるため、テーブルデータの密度が下がります。密度が下がると、読み込むデータ量が増えます(キャッシュヒット率の低下)。そのため、INSERT、SELECT処理がメインとなるテーブルについては、キャッシュヒット率を重視する意味で、FILLFACTORは指定せず、デフォルトである 100% の設定を使うほうが良いでしょう。

第三回 HOTの上手な使い方 | Let's POSTGRES

つまり、FFの調整には「HOT更新しやすくなる」メリットと、「テーブルが肥大化しやすくなり読み取りが不利になる」デメリットがあり、トレードオフになります。本記事では、このトレードオフを実験で確認します。

検証環境

Windows 11 マシンの Hyper-V 環境で検証しました。

ホスト

プロセッサ Intel Core i5-14500
メモリー 32 GB
OS Windows 11 Pro 25H2

Hyper-V

プロセッサ 10個の仮想プロセッサ
メモリー 8 GB
OS Rocky Linux release 9.7
DB PostgreSQL 18.2

検証コード/設定

検証コード及び設定は GitHub に格納しました。

GitHub - pato-taityo/fillfactor_effect

検証コードは ChatGPT で生成し、活用した部分については妥当性を確認しました。ただし、未活用の部分については十分な精査をしていません。

検証に用いた postgresql.conf も格納しています。

検証環境(10 vCPU VM)を踏まえ、並列度は次の値に変更しています。

export CLIENTS=20
export JOBS=10

検証

TPC-B(pgbenchの組み込みシナリオ)

pgbench の TPC-B に基づいたシナリオを使い、FF を 100 から 70 まで変化させて TPS を測定しました。

FF と TPS を比較した結果を示します。

TPC-BのシナリオでFFとTPSを比較した結果です

TPS に注目すると、FF=100 より FF=95 が良い結果となりました。ですが、FF<=90 では FF=100 よりも悪い結果となっています。

この結果を pgbench_accounts テーブルに着目して分析します。

pg_stat_all_tables の統計情報から、更新全体 (n_tup_upd) のうち HOT 更新 (n_tup_hot_upd) が占める割合を、HOT更新率の近似値として扱います(※統計値は累積なので、測定開始・終了時点の差分で見ています)。その結果を FF と比較したものが次です。

TPC-BのシナリオでFFとHOT更新率を比較した結果です

FF=95 の時点でほぼすべてが HOT 更新となっており、FF をさらに下げても「HOT更新率の改善」という観点では伸びしろが小さい状況でした。

一方で、pgbench_accounts テーブルのサイズは FF を下げるほど増大します。

FFとテーブルサイズを比較した結果です

テーブルサイズが増えると、同じ件数を扱っていても必要なページ数が増え、キャッシュヒット率の低下などを通じて読み取りが不利になります。

以上より、今回の検証環境下では、

  • FF=95 は HOT 更新の改善効果が有利に働き TPS が向上した
  • しかし FF を下げすぎると、テーブル肥大による悪影響が支配的になり TPS が低下した

と解釈できます。

DML単体の影響

TPC-B は複合的なシナリオだったため、次に DML 単体(SELECT / INSERT / UPDATE / DELETE)と FF の影響を確認します。

UPDATE については、HOT 更新の影響が比較しやすいように、HOT 更新が起こりにくい条件を作った update_nohot も用意しました(インデックスを設定した列を更新し、HOT更新が起こらないようにしています)。

また、UPDATE の代わりに DELETE + INSERT を行う churn と名付けたテストも含めています。

DELETE を単純に「ランダムな aid を消す」という実装にすると、時間が進むにつれて「DELETE がヒットしない(0行削除)」が増える懸念があります。そこで、pgbench_delete_queue (UNLOGGED TABLE) を用意し、DELETE が必ず既存行を削除する実装にしました。

FF と TPS を比較した結果を示します。見やすくするため、各 DML の FF=100 を基準に正規化しています。

DML操作でFFとTPSを比較した結果です

FF を低下させるに従い、概ね以下の結果となりました。

  • SELECT は TPS が著しく落ちました。FF 低下によりテーブルが肥大化し、キャッシュ効率が悪化した影響が大きいと推測しています。
  • UPDATE(HOT更新あり)は FF=90, 95 で TPS 向上が見られました。ただし改善幅は小さめで、FF<=85 では FF=100 を下回りました。
  • UPDATE(HOT更新なし)は、FF を下げるほど TPS が低下しました。HOT 更新のメリットが得られない一方で、テーブル肥大のデメリットは受けるためと考えられます。
  • INSERT はほぼ横ばいでした(少なくとも今回の条件では FF の影響は限定的でした)。
  • DELETE は ±数%程度の揺れに収まり、単回測定の範囲では明確な傾向を断定しにくい結果でした。

これらを踏まえると、FF を低下させて「全体としての性能向上」を狙うには、相当量の UPDATE があり、かつ HOT 更新が十分に見込めるワークロードでない限り難しい(少なくとも今回の条件ではそう見える)と言えそうです。

結論

実際のワークロード次第ではありますが、FF を見直して効果を得られるのは、HOT 更新の改善がボトルネックに効いてくるケースに限られそうです。
また、FF=100 でも HOT 更新は起こりうることを考えると、確証が持てない段階ではデフォルト(FF=100)で様子を見る判断も現実的だと思われます。

こぼれ話

今回の検証では AI (ChatGPT) との共同作業で行いました。AI は実験計画と検証コードを素早く準備し、検証をサポートしてくれました。また、私だけでは思いつかなかったような観点もフォローしてくれました。

ただ一方で、検証としては致命的なミスを犯すこともあり、それ故に違和感のある結果が出たとしても、無理やり説明をつけて正当化しようとする場面もありました。

AI は頼りになる味方ですが、それでも出力結果に対して批判的にチェックすべきということを忘れてはならない、と改めて感じる機会となりました。