100本ノック / 線形代数 / 線形代数100本ノック

製造業で学ぶ線形代数10選|FEM・最適化・デジタルツイン・AIをPythonで実践

線形代数でつなぐ製造現場の意思決定――設備設計・保全・品質・経営の実践10題

本記事では、線形代数100本ノックの No.091〜No.100 を、架空の精密部品工場における意思決定へ結び付けて扱います。有限要素法(FEM)からデジタルツイン、製造業DI、生成AIまで、一見異なる技術の背後にある「ベクトルで状態を表し、行列で関係や変換を表す」という共通構造を、実行可能なPythonコードで確認します。

[!NOTE] 本資料は、数理工房 (もしくは代表である和山個人) が過去に企業研修において使用した notebook を企業様の許可を得て再構成・編集のうえ公開しています。
掲載データはすべて架空のものであり、実在する企業・工場・数値とは一切関係ありません。

はじめに:この記事で扱う製造業の実務課題

製造現場では、設備の変形、配分計画、故障状態の遷移、類似品検索、需要変動などが別々の部署で扱われがちです。しかし、これらは状態をベクトル、相互作用を行列として表すことで、同じ計算基盤上で議論できます。本記事の目的は数式を覚えることではなく、どの量を状態として定義し、どの関係を行列にするかを判断できるようになることです。

現場でよくある状況

  • 設計部門は解析結果を持つが、生産条件との接続が弱い
  • 生産計画は表計算で調整され、制約や目的関数が暗黙的になっている
  • センサーデータは蓄積されるが、設備状態の推定や類似事例検索に生かし切れない
  • 経営指標と現場KPIの因果関係が部署ごとに分断されている

なぜこの問題は判断が難しいのか

観測値にはノイズがあり、状態は直接見えず、複数の制約と評価軸が競合します。また、数学的に計算できることと、現場で採用できることは同じではありません。単位、データ粒度、制約、更新頻度、説明責任まで含めてモデルを設計する必要があります。

今回扱うノックの全体像

No.テーマ製造業での問い
091FEM荷重による治具の変位は許容範囲か
092最適化問題限られた設備時間をどう配分するか
093マルコフ連鎖設備状態は将来どう推移するか
094量子力学の線形代数状態・演算子・期待値をどう読むか
095推薦システム工程条件の候補をどう提示するか
096ベクトル検索過去の類似トラブルをどう探すか
097シミュレーション不確実な需要で欠品リスクはどれほどか
098デジタルツイン実測値で仮想設備をどう更新するか
099製造業DI複数KPIから景況感をどう要約するか
100AI時代に線形代数が重要な理由AIの入出力をどう監督するか

Python環境の準備

NumPyでベクトル・行列計算、pandasで表形式の確認、SciPyで最適化、matplotlibで可視化を行います。乱数生成器は固定し、再実行しても同じ結果になるようにします。

import sys
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from scipy.optimize import linprog

try:
    import japanize_matplotlib  # 日本語表示を有効化
except ImportError:
    pass

np.set_printoptions(precision=3, suppress=True)
pd.set_option("display.precision", 3)
rng = np.random.default_rng(20250701)

print(f"Python: {sys.version.split()[0]}")
print(f"NumPy: {np.__version__}, pandas: {pd.__version__}, matplotlib: {matplotlib.__version__}")
Python: 3.13.1
NumPy: 2.5.1, pandas: 3.0.3, matplotlib: 3.11.0

架空データの作成

対象は、製品A〜Dを加工する架空の精密部品工場です。日次の需要、気温、主軸振動、加工誤差、消費電力を生成します。需要増と気温上昇が設備負荷へ波及する弱い関係を埋め込みますが、実在企業の値ではありません。

n_days = 120
day = np.arange(n_days)
temperature = 23 + 5*np.sin(2*np.pi*day/30) + rng.normal(0, 0.8, n_days)
demand = 205 + 0.28*day + 18*np.sin(2*np.pi*day/14) + rng.normal(0, 10, n_days)
vibration = 1.8 + 0.006*day + 0.035*(temperature-23) + rng.normal(0, 0.10, n_days)
machining_error = 5.0 + 0.85*vibration + 0.05*(temperature-23) + rng.normal(0, 0.25, n_days)
power = 115 + 0.16*demand + 2.2*vibration + rng.normal(0, 2.5, n_days)

factory = pd.DataFrame({
    "day": day + 1, "demand_units": demand.round(0), "temperature_C": temperature,
    "vibration_mm_s": vibration, "error_um": machining_error, "power_kWh": power
})
print(factory.head().to_string(index=False))
print("\n主要統計量")
print(factory.drop(columns="day").describe().loc[["mean", "std", "min", "max"]].round(2))
 day  demand_units  temperature_C  vibration_mm_s  error_um  power_kWh
   1         204.0         23.124           1.870     7.056    156.019
   2         211.0         24.208           1.742     6.626    154.307
   3         208.0         24.933           1.873     6.896    152.340
   4         217.0         25.779           1.889     6.629    156.710
   5         228.0         27.362           2.080     6.781    158.471

主要統計量
      demand_units  temperature_C  vibration_mm_s  error_um  power_kWh
mean        220.88          23.06            2.14      6.80     155.25
std          19.36           3.64            0.25      0.37       4.31
min         163.00          16.76            1.61      5.89     141.74
max         263.00          29.13            2.63      7.67     164.78
fig, axes = plt.subplots(2, 1, figsize=(10, 6), sharex=True)
axes[0].plot(factory["day"], factory["demand_units"], color="tab:blue")
axes[0].set(title="架空工場の日次需要", ylabel="需要(個/日)")
axes[0].grid(True, alpha=0.3)
axes[1].plot(factory["day"], factory["vibration_mm_s"], color="tab:red")
axes[1].set(title="設備振動の推移", xlabel="日", ylabel="振動(mm/s)")
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

png

No.091:FEM――治具の変位を連立方程式として評価する

実務での意味

治具やフレームが荷重で変形すると、加工精度や工具寿命に影響します。有限要素法(FEM)では連続体を小さな要素に分け、節点変位を未知数として変形を計算します。ここでは1次元ばね要素に単純化し、計算の骨格を確認します。

分析・モデル化の考え方

静的な線形FEMの基本式は

Ku=f\mathbf{K}\mathbf{u}=\mathbf{f}

です。K\mathbf{K}は剛性行列、u\mathbf{u}は節点変位、f\mathbf{f}は外力です。要素剛性 k=EA/Lk=EA/L を全体行列へ組み立て、固定端の自由度を除いて解きます。実務では材料非線形、接触、温度、境界条件の妥当性も検証対象です。

Pythonで確認する

E, area, length = 210e9, 4.0e-4, 0.50  # Pa, m^2, m
k = E * area / length
K = k * np.array([[1, -1, 0], [-1, 2, -1], [0, -1, 1]], dtype=float)
force = np.array([0, 0, 20_000.0])
u = np.zeros(3)
u[1:] = np.linalg.solve(K[1:, 1:], force[1:])
fem_result = pd.DataFrame({"節点": [0, 1, 2], "位置_m": [0, .5, 1.0], "変位_mm": u*1e3})
print(fem_result.to_string(index=False))

plt.figure(figsize=(8, 4))
plt.plot(fem_result["位置_m"], fem_result["変位_mm"], marker="o")
plt.title("簡易FEMによる治具の節点変位")
plt.xlabel("位置(m)"); plt.ylabel("変位(mm)"); plt.grid(True, alpha=.3); plt.tight_layout(); plt.show()
 節点  位置_m  変位_mm
  0   0.0  0.000
  1   0.5  0.119
  2   1.0  0.238


png

結果の読み取り

自由端ほど変位が大きくなり、最大変位は約0.24 mmです。仮に許容値が0.10 mmなら設計変更が必要です。ただし、メッシュを細かくしただけで結果が正しくなるわけではなく、固定条件・荷重方向・材料定数が現物と一致しているかを設計レビューで確認します。

No.092:最適化問題――設備時間を利益へ変換する

実務での意味

受注をすべて作れないとき、声の大きい案件から処理するのではなく、利益、設備時間、需要上限を明示して生産数量を決めます。

分析・モデル化の考え方

製品別数量を x\mathbf{x}、限界利益を c\mathbf{c}、設備使用係数を A\mathbf{A}、能力を b\mathbf{b} とすると、

\mathrm{s.t.}\quad \mathbf{A}\mathbf{x}\leq\mathbf{b},\;\mathbf{x}\geq0$$ という線形計画になります。係数は会計・現場双方で合意し、段取り、ロット、納期は必要に応じて整数制約として追加します。 ### Pythonで確認する ```python products = np.array(["製品A", "製品B", "製品C", "製品D"]) profit = np.array([42, 55, 38, 70]) # 百円/個 A = np.array([[1.2, 1.8, 1.0, 2.4], [0.8, 0.6, 1.5, 1.2]]) capacity = np.array([520, 360]) demand_max = np.array([180, 140, 160, 100]) opt = linprog(-profit, A_ub=A, b_ub=capacity, bounds=list(zip(np.zeros(4), demand_max)), method="highs") plan = pd.DataFrame({"製品": products, "生産数量": opt.x, "需要上限": demand_max, "限界利益_百円": profit, "利益貢献_百円": opt.x*profit}) print(plan.round(1).to_string(index=False)) print(f"\n総限界利益: {-opt.fun:,.0f} 百円") print("設備使用量 / 能力:", np.round(A @ opt.x, 1), "/", capacity) ``` 製品 生産数量 需要上限 限界利益_百円 利益貢献_百円 製品A 180.0 180 42 7560.0 製品B 114.3 140 55 6285.7 製品C 98.3 160 38 3734.9 製品D 0.0 100 70 0.0 総限界利益: 17,581 百円 設備使用量 / 能力: [520. 360.] / [520 360] ### 結果の読み取り 最適解では能力を価値の高い製品へ配分し、どの設備が上限に達したかも確認できます。小数解は基準計画であり、実際にはロット単位へ丸めた後に制約違反がないか再評価します。利益係数を±10%変えた感度分析も、計画の頑健性確認に有効です。 ## No.093:マルコフ連鎖――設備状態の将来分布を予測する ### 実務での意味 設備が「正常・注意・故障」の間をどう遷移するかを把握すると、停止後の対応ではなく、将来の故障確率に基づく保全要員・予備品計画が可能になります。 ### 分析・モデル化の考え方 遷移行列 $\mathbf{P}$ の各行は現在状態、各列は翌日状態を表し、行和は1です。状態確率 $\boldsymbol{\pi}_t$ は $\boldsymbol{\pi}_{t+1}=\boldsymbol{\pi}_t\mathbf{P}$ で更新されます。履歴依存を無視する仮定が強すぎないかも確認します。 ### Pythonで確認する ```python states = ["正常", "注意", "故障"] P = np.array([[.92, .075, .005], [.25, .65, .10], [.55, .30, .15]]) pi = np.array([1., 0., 0.]) history = [pi.copy()] for _ in range(30): pi = pi @ P history.append(pi.copy()) markov = pd.DataFrame(history, columns=states) print(markov.iloc[[0, 1, 7, 14, 30]].round(3)) plt.figure(figsize=(8, 4)) for s in states: plt.plot(markov.index, markov[s], label=s) plt.title("設備状態確率の推移"); plt.xlabel("経過日"); plt.ylabel("状態確率") plt.grid(True, alpha=.3); plt.legend(); plt.tight_layout(); plt.show() ``` 正常 注意 故障 0 1.000 0.000 0.000 1 0.920 0.075 0.005 7 0.790 0.184 0.026 14 0.782 0.191 0.027 30 0.782 0.191 0.027 ![png](/blog/100-knock/10-linear-algebra/10_nb/10_nb_14_1.png) ### 結果の読み取り 正常から開始しても、時間とともに注意・故障の確率が蓄積し、一定の分布へ近づきます。30日目の故障確率は「30日以内に一度でも故障する確率」ではなく、**30日目時点で故障状態にいる確率**です。この違いを保全KPIで混同しないことが重要です。 ## No.094:量子力学の線形代数――状態・演算子・期待値を理解する ### 実務での意味 量子計算を直ちに工場へ導入する話ではありません。量子力学では、状態を複素ベクトル、観測量を行列として表すため、線形代数の意味を凝縮した教材になります。量子センシングや材料計算の技術評価でも基本語彙になります。 ### 分析・モデル化の考え方 規格化された状態 $|\psi\rangle$ に対し、観測量をエルミート行列 $\mathbf{H}$ で表します。期待値は $\langle H\rangle=\langle\psi|\mathbf{H}|\psi\rangle$ です。固有値は測定結果候補、固有ベクトルへの射影の絶対値二乗が確率になります。 ### Pythonで確認する ```python psi = np.array([np.sqrt(.7), np.exp(1j*np.pi/4)*np.sqrt(.3)]) H = np.array([[1.0, 0.2-0.1j], [0.2+0.1j, 2.0]]) eigenvalues, eigenvectors = np.linalg.eigh(H) probabilities = np.abs(eigenvectors.conj().T @ psi)**2 expected = np.vdot(psi, H @ psi).real quantum = pd.DataFrame({"測定値(固有値)": eigenvalues, "測定確率": probabilities}) print(quantum.round(4).to_string(index=False)) print(f"確率和: {probabilities.sum():.4f}, 期待値: {expected:.4f}") ``` 測定値(固有値) 測定確率 0.952 0.505 2.048 0.495 確率和: 1.0000, 期待値: 1.4944 ### 結果の読み取り 測定確率の和は1になり、期待値は固有値の確率加重平均と一致します。複素数が登場しても、意思決定の構造は「状態×変換×評価」です。技術選定では、量子優位性の宣伝ではなく、対象問題、誤差、古典計算との比較条件を明示します。 ## No.095:推薦システム――工程条件の候補を補完する ### 実務での意味 品種と加工条件の組合せが増えると、すべてを試験できません。過去の評価行列から未試験条件の候補を提示し、熟練者の探索範囲を絞ります。 ### 分析・モデル化の考え方 品種×条件の評価行列 $\mathbf{R}$ を低ランク行列 $\mathbf{U}_k\mathbf{\Sigma}_k\mathbf{V}_k^{\mathsf T}$ で近似します。欠損値を単純補完した教育用例であり、本番では観測済み要素だけの損失、バイアス、時系列分割、安全制約を扱います。 ### Pythonで確認する ```python R = np.array([[92, 88, np.nan, 70], [85, np.nan, 80, 65], [60, 68, 90, np.nan], [np.nan, 72, 94, 88], [78, 82, np.nan, 74]], float) row_mean = np.nanmean(R, axis=1, keepdims=True) filled = np.where(np.isnan(R), row_mean, R) U, s, Vt = np.linalg.svd(filled, full_matrices=False) pred = (U[:, :2] * s[:2]) @ Vt[:2] rows, cols = np.where(np.isnan(R)) recommendations = pd.DataFrame({"品種": [f"品種{i+1}" for i in rows], "未試験条件": [f"条件{j+1}" for j in cols], "予測評価": pred[rows, cols]}) print(recommendations.sort_values("予測評価", ascending=False).round(1).to_string(index=False)) ``` 品種 未試験条件 予測評価 品種1 条件3 82.3 品種5 条件3 81.4 品種4 条件1 79.5 品種2 条件2 78.9 品種3 条件4 76.4 ### 結果の読み取り 予測評価の高い未試験条件を優先候補にできます。ただし推薦値は品質保証ではなく、追加試験の順序付けです。安全や規格適合を満たさない条件を事前に除外し、採用後の実測結果を行列へ戻す運用が必要です。 ## No.096:ベクトル検索――過去の類似トラブルを探す ### 実務での意味 トラブル記録の表現が担当者ごとに異なっても、振動・温度・電力・誤差などを共通ベクトル化すれば、現在事象に近い過去事例を検索できます。 ### 分析・モデル化の考え方 尺度差を標準化したベクトル $\mathbf{x},\mathbf{y}$ に対し、コサイン類似度 $\cos\theta=\mathbf{x}^{\mathsf T}\mathbf{y}/(\|\mathbf{x}\|_2\|\mathbf{y}\|_2)$ を使います。標準化条件、特徴量の重み、検索結果の正解定義が性能を左右します。 ### Pythonで確認する ```python features = factory[["temperature_C", "vibration_mm_s", "error_um", "power_kWh"]] Z = (features - features.mean()) / features.std(ddof=0) query = Z.iloc[-1].to_numpy() past = Z.iloc[:-1].to_numpy() similarity = past @ query / (np.linalg.norm(past, axis=1)*np.linalg.norm(query)) top = np.argsort(similarity)[-5:][::-1] search_result = factory.iloc[top][["day", "temperature_C", "vibration_mm_s", "error_um", "power_kWh"]].copy() search_result["cosine_similarity"] = similarity[top] print("検索対象: 120日目") print(search_result.round(3).to_string(index=False)) ``` 検索対象: 120日目 day temperature_C vibration_mm_s error_um power_kWh cosine_similarity 114 18.442 2.376 6.683 164.381 0.950 91 22.531 2.322 6.633 157.342 0.878 87 20.357 2.299 6.824 159.235 0.873 77 23.134 2.204 6.860 163.935 0.838 115 17.441 2.277 6.833 162.336 0.823 ### 結果の読み取り 類似度上位日は、現在の状態に近い事例の調査入口になります。近い値でも原因が同じとは限りません。交換部品、アラーム、作業記録を併記し、保全担当者の評価を検索品質へフィードバックします。 ## No.097:シミュレーション――需要変動下の在庫方針を比べる ### 実務での意味 平均需要だけで安全在庫を決めると、変動が大きい時期の欠品を見落とします。多数の需要シナリオを生成し、サービス水準と在庫量の関係を比較します。 ### 分析・モデル化の考え方 相関を持つ多品種需要を $\mathbf{d}=\boldsymbol{\mu}+\mathbf{L}\mathbf{z}$ と生成します。$\mathbf{L}$ は共分散行列のCholesky因子です。相関を無視すると、同時欠品や能力集中のリスクを過小評価し得ます。 ### Pythonで確認する ```python mu = np.array([210, 150, 120]) cov = np.array([[625, 180, 90], [180, 400, 120], [90, 120, 225]]) L = np.linalg.cholesky(cov) sim_demand = mu + rng.standard_normal((10000, 3)) @ L.T safety_levels = np.array([0.0, 0.5, 1.0, 1.5, 2.0]) rows = [] std = np.sqrt(np.diag(cov)) for z in safety_levels: stock = mu + z*std fill_rate = np.minimum(sim_demand, stock).sum() / sim_demand.sum() all_filled = np.mean(np.all(sim_demand <= stock, axis=1)) rows.append((z, stock.sum(), fill_rate, all_filled)) policy = pd.DataFrame(rows, columns=["安全係数", "総在庫", "数量充足率", "全品種同時充足率"]) print(policy.round(3).to_string(index=False)) plt.figure(figsize=(8, 4)) plt.plot(policy["総在庫"], policy["数量充足率"], marker="o", label="数量充足率") plt.plot(policy["総在庫"], policy["全品種同時充足率"], marker="s", label="全品種同時充足率") plt.title("在庫量とサービス水準のトレードオフ"); plt.xlabel("総在庫(個)"); plt.ylabel("サービス水準") plt.grid(True, alpha=.3); plt.legend(); plt.tight_layout(); plt.show() ``` 安全係数 総在庫 数量充足率 全品種同時充足率 0.0 480.0 0.949 0.207 0.5 510.0 0.975 0.407 1.0 540.0 0.989 0.642 1.5 570.0 0.996 0.826 2.0 600.0 0.999 0.933 ![png](/blog/100-knock/10-linear-algebra/10_nb/10_nb_26_1.png) ### 結果の読み取り 在庫を増やすほど充足率は上がりますが、増分効果は次第に小さくなります。また、数量充足率が高くても全品種を同時に満たす確率は低めです。経営会議では、どのサービス水準を契約・顧客価値として守るのかを先に定義します。 ## No.098:デジタルツイン――実測値で仮想設備を更新する ### 実務での意味 デジタルツインは3D表示だけではありません。物理モデルによる予測をセンサー観測で継続的に補正し、見えない設備状態を推定する仕組みです。 ### 分析・モデル化の考え方 状態 $\mathbf{x}_t$ を遷移行列 $\mathbf{F}$ で予測し、観測 $\mathbf{y}_t$ と観測行列 $\mathbf{H}$ から残差を計算します。ここでは定常Kalmanフィルタ型の更新 $\hat{\mathbf{x}}\leftarrow\hat{\mathbf{x}}+\mathbf{K}(\mathbf{y}-\mathbf{H}\hat{\mathbf{x}})$ を簡略実装します。 ### Pythonで確認する ```python observed = factory[["vibration_mm_s", "temperature_C"]].to_numpy() F = np.array([[1.0, 0.002], [0.0, 1.0]]) H = np.eye(2) gain = np.diag([0.35, 0.55]) x = observed[0].copy() estimated = [] for y in observed: x_pred = F @ x x = x_pred + gain @ (y - H @ x_pred) estimated.append(x.copy()) estimated = np.array(estimated) plt.figure(figsize=(9, 4)) plt.plot(factory["day"], observed[:, 0], alpha=.45, label="実測振動") plt.plot(factory["day"], estimated[:, 0], linewidth=2, label="ツイン推定") plt.title("実測値によるデジタルツイン状態の更新"); plt.xlabel("日"); plt.ylabel("振動(mm/s)") plt.grid(True, alpha=.3); plt.legend(); plt.tight_layout(); plt.show() print(f"最終日の実測振動={observed[-1,0]:.3f}, 推定振動={estimated[-1,0]:.3f} mm/s") ``` ![png](/blog/100-knock/10-linear-algebra/10_nb/10_nb_29_0.png) 最終日の実測振動=2.366, 推定振動=2.414 mm/s ### 結果の読み取り 推定値は実測ノイズを平滑化しながら変化へ追随します。ゲインが大きいほど実測に敏感、小さいほど物理モデルを重視します。本番ではセンサー校正、通信欠損、モデル更新の責任者、異常時のフェイルセーフを運用設計に含めます。 ## No.099:製造業DI――複数KPIから共通の変化を抽出する ### 実務での意味 製造業DI(Diffusion Index)は、改善・横ばい・悪化の広がりを要約する指標です。ここでは現場KPIの標準化と主成分を組み合わせ、受注・稼働・品質・在庫の共通方向を確認します。 ### 分析・モデル化の考え方 回答型DIは一般に「改善割合−悪化割合」です。一方、連続KPIでは標準化行列 $\mathbf{Z}$ の共分散行列を固有分解し、第1固有ベクトルを共通因子の重みとして使えます。符号は任意なので、受注増が正となるよう揃えます。 ### Pythonで確認する ```python months = pd.date_range("2025-01-01", periods=12, freq="MS") latent = np.linspace(-1.2, 1.1, 12) + rng.normal(0, .25, 12) kpi = pd.DataFrame({ "受注": 100 + 12*latent + rng.normal(0, 3, 12), "稼働率": 78 + 5*latent + rng.normal(0, 1.5, 12), "良品率": 96 + .7*latent + rng.normal(0, .25, 12), "在庫回転": 7 + .8*latent + rng.normal(0, .3, 12), }, index=months) Z = (kpi-kpi.mean())/kpi.std(ddof=0) eigval, eigvec = np.linalg.eigh(np.cov(Z, rowvar=False, ddof=0)) weights = eigvec[:, -1] if weights[0] < 0: weights *= -1 di = Z @ weights / np.linalg.norm(weights) print(pd.DataFrame({"KPI": kpi.columns, "DIへの重み": weights}).round(3).to_string(index=False)) print(f"第1主成分の説明率: {eigval[-1]/eigval.sum():.1%}") plt.figure(figsize=(9, 4)) plt.plot(months, di, marker="o"); plt.axhline(0, color="black", linewidth=.8) plt.title("架空工場の製造業DI(標準化指数)"); plt.xlabel("月"); plt.ylabel("DI") plt.grid(True, alpha=.3); plt.tight_layout(); plt.show() ``` KPI DIへの重み 受注 0.518 稼働率 0.507 良品率 0.490 在庫回転 0.485 第1主成分の説明率: 88.9% ![png](/blog/100-knock/10-linear-algebra/10_nb/10_nb_32_1.png) ### 結果の読み取り 正のDIは複数KPIが平均より良い共通局面、負は弱い局面を示します。説明率が低ければ1本の指数への要約は危険です。重みを毎月再推定すると指標の意味が変わるため、基準期間と改定ルールを固定し、元KPIも併記します。 ## No.100:AI時代に線形代数が重要な理由――埋め込みとAttentionを監督する ### 実務での意味 生成AIは、手順書・異常記録・図面属性などをベクトルへ変換し、関連情報を検索・統合します。利用者が線形代数を理解すると、類似度、重み、次元、正規化というAIの挙動を検証できます。 ### 分析・モデル化の考え方 Attentionは、問い合わせ $\mathbf{Q}$ とキー $\mathbf{K}$ の内積をsoftmaxで重みに変え、値 $\mathbf{V}$ を加重和します。 $$\operatorname{Attention}(Q,K,V)=\operatorname{softmax}\left(\frac{QK^{\mathsf T}}{\sqrt{d}}\right)V$$ 重みは説明の手掛かりですが、因果的な根拠や正しさの保証ではありません。 ### Pythonで確認する ```python labels = ["主軸振動", "冷却液温度", "加工誤差", "工具使用時間"] K_ai = np.array([[.9,.1,.2], [.1,.9,.2], [.7,.2,.6], [.5,.1,.8]]) V_ai = np.array([[.8,.2], [.2,.4], [.9,.7], [.6,.9]]) # 異常、保全の情報量 Q_ai = np.array([[.8,.1,.7]]) # 「加工精度悪化の原因」 scores = Q_ai @ K_ai.T / np.sqrt(K_ai.shape[1]) attention = np.exp(scores-scores.max()) attention /= attention.sum(axis=1, keepdims=True) context = attention @ V_ai ai_result = pd.DataFrame({"情報源": labels, "Attention重み": attention.ravel()}) print(ai_result.sort_values("Attention重み", ascending=False).round(3).to_string(index=False)) print("統合コンテキスト [異常, 保全] =", context.round(3)) plt.figure(figsize=(8, 4)) plt.bar(labels, attention.ravel(), color="tab:purple") plt.title("問い合わせに対するAttention重み"); plt.xlabel("情報源"); plt.ylabel("重み") plt.grid(True, axis="y", alpha=.3); plt.tight_layout(); plt.show() ``` 情報源 Attention重み 加工誤差 0.279 工具使用時間 0.274 主軸振動 0.259 冷却液温度 0.187 統合コンテキスト [異常, 保全] = [[0.661 0.569]] ![png](/blog/100-knock/10-linear-algebra/10_nb/10_nb_35_1.png) ### 結果の読み取り 問い合わせベクトルとの内積が大きい情報源ほど重みが高くなり、その値ベクトルが回答へ強く反映されます。AI導入では、検索対象文書の版管理、アクセス権、引用元表示、人による承認、誤回答時の記録を整えます。線形代数はモデルを自作するためだけでなく、**AIの出力を監督する共通言語**です。 ## 対象ノックを通して見える実務上の示唆 10題に共通するのは、現実をベクトルに変換し、関係を行列にし、目的に応じた出力へ変換する流れです。 1. **状態定義が先、アルゴリズムが後**:何を一つの状態・行・列とみなすかが結果を決めます。 2. **単位と尺度を管理する**:剛性、需要、振動、文章特徴を無造作に混ぜないことが重要です。 3. **制約と不確実性を明示する**:最適解や予測値を確定値として扱わず、許容範囲や感度を示します。 4. **人の判断を置き換えず、判断材料を整える**:推薦・検索・DI・AIは、検証すべき候補を絞る道具です。 ## 実務導入する場合に必要なこと - 経営課題とKPIを結び付け、誤差を許容できる範囲を決める - データ定義、単位、欠損、センサー校正、版管理を標準化する - 学習・検証期間を分離し、現行方法との比較指標を合意する - 現場担当者を含む小規模PoCで、運用負荷と例外処理を確認する - モデル所有者、承認者、更新頻度、停止条件、監査ログを定める - 効果を精度だけでなく、停止時間、歩留まり、在庫、判断時間で評価する ## まとめ FEM、最適化、状態遷移、推薦、検索、シミュレーション、デジタルツイン、DI、AIは、線形代数という共通基盤でつながっています。重要なのは難しい式を暗記することではなく、状態・関係・目的・制約を行列とベクトルへ正しく翻訳し、結果を現場の判断へ戻すことです。本Notebookは小さな再現例なので、実導入時には現物データと業務制約で段階的に検証してください。 ## 法人向けのご相談 数理工房では、製造データの整理、数理モデル設計、PoC、現場実装、研修まで、課題の成熟度に合わせてご支援します。「データはあるがテーマが定まらない」「解析結果を意思決定につなげたい」といった初期段階からご相談いただけます。 > 📩 **お問い合わせ**: [surikobo.co.jp/contact](https://surikobo.co.jp/contact) > まずはお気軽にご相談ください。