100本ノック / 機械学習 / 実務機械学習100本ノック

製造業の顧客クラスタリングと製品推薦をPythonで実践|機械学習100本ノック

製造業の提案力を高める顧客セグメント分析と製品推薦

機械学習100本ノック No.081〜No.090:クラスタリング・類似検索・協調フィルタリング

設備・部品メーカーが保有する顧客属性、取引実績、製品仕様を使い、**「どの顧客に、どの製品を、なぜ提案するか」**を再現可能な分析へ変える実務編です。KMeans、PCA、類似度、ユーザー×アイテム行列、協調フィルタリングを、一つの営業企画シナリオで接続します。

この notebook で扱うデータ・分析結果は研修用の架空例です。推薦結果は営業判断を支援する候補であり、自動的に採用すべき結論ではありません。

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

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

製造業の法人営業では、顧客数と製品数が増えるほど、担当者の経験だけで提案機会を拾うことが難しくなります。本稿では、産業機器メーカーの営業企画部が、顧客企業を理解し、似た顧客や製品を探し、購買履歴から次の提案候補を作る状況を想定します。

目標は「推薦モデルを作ること」ではありません。限られた営業工数を、顧客課題との適合度が高い候補へ配分するための判断材料を作ることです。

2. 現場でよくある状況

  • 顧客区分が売上規模だけで、設備構成や保全課題の違いを表せていない
  • 製品検索が型番や担当者の記憶に依存し、代替品・関連品を見落とす
  • 購買履歴は基幹システムにあるが、未購入品の提案に活用できていない
  • 推薦件数は出せても、正しかったかを定量評価していない

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

「似ている」には、売上規模、設備台数、停止損失、品質要求、製品仕様、購買パターンなど複数の定義があります。また、購買がないことは不要を意味せず、単に未提案・更新前・他社購入かもしれません。したがって、距離や予測スコアを業務文脈と切り離して解釈しないことが重要です。

4. 今回扱うノックの全体像

No.手法意思決定への接続
081〜085KMeans、クラスタ数評価、PCA顧客群の理解と営業施策の設計
086〜087コサイン類似度・近傍探索類似製品、類似顧客の探索
088〜089購買行列・協調フィルタリングクロスセル候補の順位付け
090Precision@K・Recall@K推薦施策を導入するかの検証

5. Python 環境の準備

外部データや seaborn は使いません。乱数生成器を 42 に固定し、同じ結果を再現できるようにします。標準化は単位の違う特徴量が距離を支配しないために必要です。

import sys
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt

from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.preprocessing import StandardScaler

SEED = 42
rng = np.random.default_rng(SEED)
plt.rcParams["figure.figsize"] = (8, 4.8)
plt.rcParams["axes.unicode_minus"] = False

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

6. 架空データの作成

120社の顧客企業について、年間購買額、設備台数、予防保全比率、品質要求度、停止損失を生成します。潜在的に「小規模・価格重視」「中規模・バランス」「大規模・安定稼働重視」の3群がある設定ですが、分析時には正解ラベルを使いません。

別に12製品の仕様データと、過去の購買有無も作ります。購買確率は顧客特性と製品カテゴリの適合度で変化させ、現実の疎な購買行列を模します。

n_customers = 120
segment = np.repeat([0, 1, 2], [40, 45, 35])
params = {
    0: ([25, 12, 0.30, 45, 1.5], [7, 4, .10, 9, .5]),
    1: ([70, 32, 0.58, 68, 4.5], [13, 7, .10, 8, 1.0]),
    2: ([155, 68, 0.82, 87, 10.0], [25, 12, .07, 5, 2.0]),
}
raw = np.vstack([rng.normal(params[s][0], params[s][1]) for s in segment])
raw[:, 0:2] = np.maximum(raw[:, 0:2], 1)
raw[:, 2] = np.clip(raw[:, 2], 0.05, 0.98)
raw[:, 3] = np.clip(raw[:, 3], 20, 100)
raw[:, 4] = np.maximum(raw[:, 4], 0.2)

feature_cols = ["annual_purchase_mjpy", "installed_machines", "preventive_ratio", "quality_requirement", "downtime_loss_mjpy"]
customers = pd.DataFrame(raw, columns=feature_cols)
customers.insert(0, "customer_id", [f"C{i:03d}" for i in range(1, n_customers + 1)])
customers.head().round(2)
customer_id annual_purchase_mjpy installed_machines preventive_ratio quality_requirement downtime_loss_mjpy
0 C001 27.13 7.84 0.38 53.47 0.52
1 C002 15.88 12.51 0.27 44.85 1.07
2 C003 31.16 15.11 0.31 55.15 1.73
3 C004 18.98 13.48 0.20 52.91 1.48
4 C005 23.71 9.28 0.42 43.61 1.29
products = pd.DataFrame({
    "product_id": [f"P{i:02d}" for i in range(1, 13)],
    "product_name": ["標準センサー", "高精度センサー", "耐熱センサー", "標準モーター", "省エネモーター", "高トルクモーター",
                     "簡易監視端末", "予知保全端末", "品質検査カメラ", "交換部品キット", "遠隔保守契約", "省エネ診断"],
    "category": ["sensor"]*3 + ["motor"]*3 + ["digital"]*3 + ["service"]*3,
    "price_index": [25, 58, 62, 45, 70, 76, 30, 82, 88, 18, 55, 48],
    "precision": [45, 88, 72, 50, 65, 70, 42, 78, 95, 35, 60, 55],
    "durability": [50, 68, 92, 64, 75, 90, 45, 80, 68, 55, 70, 50],
    "digital_level": [25, 45, 35, 20, 45, 25, 65, 95, 85, 15, 90, 72],
})

affinity = np.column_stack([
    0.8 - customers["quality_requirement"].to_numpy()/150,
    customers["installed_machines"].to_numpy()/100,
    (customers["preventive_ratio"].to_numpy() + customers["quality_requirement"].to_numpy()/100)/2,
    customers["preventive_ratio"].to_numpy(),
])
cat_index = products["category"].map({"sensor":0, "motor":1, "digital":2, "service":3}).to_numpy()
base = affinity[:, cat_index] + (100-products["price_index"].to_numpy())[None, :] / 500
prob = np.clip(0.08 + 0.48*base + rng.normal(0, .04, (n_customers, 12)), .03, .82)
purchase = (rng.random((n_customers, 12)) < prob).astype(int)
purchase_df = pd.DataFrame(purchase, index=customers.customer_id, columns=products.product_id)

print("顧客数:", len(customers), "製品数:", len(products))
print("購買行列の密度:", f"{purchase.mean():.1%}")
products
顧客数: 120 製品数: 12
購買行列の密度: 35.4%
product_id product_name category price_index precision durability digital_level
0 P01 標準センサー sensor 25 45 50 25
1 P02 高精度センサー sensor 58 88 68 45
2 P03 耐熱センサー sensor 62 72 92 35
3 P04 標準モーター motor 45 50 64 20
4 P05 省エネモーター motor 70 65 75 45
5 P06 高トルクモーター motor 76 70 90 25
6 P07 簡易監視端末 digital 30 42 45 65
7 P08 予知保全端末 digital 82 78 80 95
8 P09 品質検査カメラ digital 88 95 68 85
9 P10 交換部品キット service 18 35 55 15
10 P11 遠隔保守契約 service 55 60 70 90
11 P12 省エネ診断 service 48 55 50 72

No.081:KMeansで顧客をクラスタリングする

実務での意味

顧客群をデータで整理すると、担当割当、セミナー内容、提案テンプレートを群ごとに設計できます。売上だけでなく保全成熟度や停止損失も含め、営業施策に意味のある軸を作ります。

分析・モデル化の考え方

KMeansは各顧客を最も近い重心へ割り当て、クラスタ内平方和を最小化します。特徴量を標準化した後で3群に分け、元単位の平均値に戻して解釈します。

Pythonで確認する

scaler = StandardScaler()
X = scaler.fit_transform(customers[feature_cols])
kmeans = KMeans(n_clusters=3, random_state=SEED, n_init=20)
customers["cluster"] = kmeans.fit_predict(X)
cluster_profile = customers.groupby("cluster")[feature_cols].agg(["mean", "count"])
cluster_profile.round(2)
annual_purchase_mjpy installed_machines preventive_ratio quality_requirement downtime_loss_mjpy
mean count mean count mean count mean count mean count
cluster
0 69.28 45 31.49 45 0.60 45 67.09 45 4.50 45
1 148.36 35 69.05 35 0.83 35 86.00 35 10.15 35
2 25.22 40 11.85 40 0.28 40 46.73 40 1.42 40

結果の読み取り

クラスタ平均を見ることで、規模だけでなく保全・品質要求の組合せを言語化できます。番号自体に順序はありません。営業企画では、各群へ『効率運用型』『成長設備型』『安定稼働重視型』など、行動につながる名称を関係者と付けます。

No.082:エルボー法でクラスタ数を決める

実務での意味

クラスタ数を先に3と決め打ちすると、組織都合に合わせた分類になりがちです。複雑さを増やしたとき、群内のばらつきがどこまで改善するかを確認します。

分析・モデル化の考え方

目的関数は SSE=kiCkxiμk2\mathrm{SSE}=\sum_k\sum_{i\in C_k}\lVert x_i-\mu_k\rVert^2 です。クラスタ数を増やせばSSEは必ず下がるため、低下が緩やかになる折れ曲がりを候補にします。

Pythonで確認する

ks = range(1, 9)
inertias = [KMeans(n_clusters=k, random_state=SEED, n_init=20).fit(X).inertia_ for k in ks]
plt.plot(list(ks), inertias, marker="o")
plt.title("Elbow method for customer clusters")
plt.xlabel("Number of clusters k")
plt.ylabel("Within-cluster SSE")
plt.grid(True, alpha=.3)
plt.tight_layout()
plt.show()
pd.DataFrame({"k": list(ks), "SSE": np.round(inertias, 1)})

png

k SSE
0 1 600.0
1 2 190.7
2 3 77.4
3 4 67.6
4 5 59.2
5 6 53.8
6 7 49.2
7 8 46.2

結果の読み取り

SSEの改善が大きい区間と、その後の緩やかな区間を比較します。折れ曲がりは唯一の正解ではありません。営業組織が運用できる施策数や、各群の最低顧客数も合わせて決めます。

No.083:シルエット係数を確認する

実務での意味

エルボー法の目視だけでなく、各顧客が自群にまとまり、他群から離れているかを数値化します。境界顧客を例外扱いする判断にも使えます。

分析・モデル化の考え方

各点について、同じクラスタへの平均距離を a(i)a(i)、最も近い他クラスタへの平均距離を b(i)b(i) とすると、s(i)=(b(i)a(i))/max(a(i),b(i))s(i)=(b(i)-a(i))/\max(a(i),b(i)) です。1に近いほど分離が明瞭です。

Pythonで確認する

silhouette_rows = []
for k in range(2, 9):
    labels = KMeans(n_clusters=k, random_state=SEED, n_init=20).fit_predict(X)
    silhouette_rows.append((k, silhouette_score(X, labels)))
silhouette_df = pd.DataFrame(silhouette_rows, columns=["k", "silhouette"])
print(silhouette_df.round(3).to_string(index=False))
best_k = int(silhouette_df.loc[silhouette_df.silhouette.idxmax(), "k"])
print(f"\n最大値となる候補: k={best_k}")
 k  silhouette
 2       0.597
 3       0.600
 4       0.507
 5       0.385
 6       0.276
 7       0.255
 8       0.256

最大値となる候補: k=3

結果の読み取り

係数が最大のkは統計的な有力候補です。ただし、僅差なら運用の簡潔さを優先できます。低い係数は失敗とは限らず、顧客が連続的に変化して明瞭な群がない可能性を示します。

No.084:PCAで次元削減する

実務での意味

5つの顧客指標を2軸へ圧縮し、顧客差を説明しやすくします。ダッシュボードの見やすさのためだけでなく、どの変数が軸を作るかも確認します。

分析・モデル化の考え方

PCAは分散が最大となる直交方向へデータを射影します。第1・第2主成分の寄与率と負荷量を確認し、2次元で失われる情報量を明示します。主成分の符号は反転しても意味は同じです。

Pythonで確認する

pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
loadings = pd.DataFrame(pca.components_.T, index=feature_cols, columns=["PC1", "PC2"])
print("寄与率:", np.round(pca.explained_variance_ratio_, 3))
print("累積寄与率:", round(pca.explained_variance_ratio_.sum(), 3))
loadings.round(3)
寄与率: [0.885 0.04 ]
累積寄与率: 0.926
PC1 PC2
annual_purchase_mjpy 0.450 -0.347
installed_machines 0.456 -0.346
preventive_ratio 0.441 0.492
quality_requirement 0.440 0.610
downtime_loss_mjpy 0.449 -0.382

結果の読み取り

累積寄与率がどの程度かを見て、2軸表示が元情報をどれだけ保持するか判断します。負荷量の絶対値が大きい特徴量から、PC1・PC2を『規模・重要度』『保全姿勢』などと業務用語へ翻訳します。

No.085:クラスタを2次元で可視化する

実務での意味

クラスタの重なりや外れた顧客を可視化すると、標準施策を適用しにくい境界顧客を営業レビューへ回せます。

分析・モデル化の考え方

PCA座標を散布図にし、KMeansの割当を色で表します。PCAは可視化用、クラスタリングは標準化済み5次元で行っており、2次元だけで再学習していない点が重要です。

Pythonで確認する

fig, ax = plt.subplots()
for c in sorted(customers.cluster.unique()):
    mask = customers.cluster.to_numpy() == c
    ax.scatter(X_pca[mask, 0], X_pca[mask, 1], label=f"Cluster {c}", alpha=.75)
ax.set_title("Customer clusters projected onto PCA space")
ax.set_xlabel("Principal component 1")
ax.set_ylabel("Principal component 2")
ax.grid(True, alpha=.3)
ax.legend()
plt.tight_layout()
plt.show()

png

結果の読み取り

群が概ね分かれていれば施策の説明がしやすくなります。重なる点は『誤分類』と即断せず、複数施策の対象候補です。図上の距離は2成分への射影後なので、元の5次元距離とは一致しません。

No.086:類似商品を検索する

実務での意味

廃番代替、上位機種、セット提案では、仕様の近い製品を素早く列挙する必要があります。属人的な型番知識を補助できます。

分析・モデル化の考え方

価格、精度、耐久性、デジタル度を標準化し、ベクトルの向きが近い製品をコサイン類似度で検索します。カテゴリは意図的に除外し、カテゴリを越えた候補も発見できるようにします。

Pythonで確認する

product_features = ["price_index", "precision", "durability", "digital_level"]
Xp = StandardScaler().fit_transform(products[product_features])
product_sim = cosine_similarity(Xp)
query_idx = products.index[products.product_name == "予知保全端末"][0]
order = np.argsort(product_sim[query_idx])[::-1]
similar_products = products.loc[order[order != query_idx][:4], ["product_id", "product_name", "category"]].copy()
similar_products["cosine_similarity"] = product_sim[query_idx, order[order != query_idx][:4]]
similar_products.round(3)
product_id product_name category cosine_similarity
8 P09 品質検査カメラ digital 0.866
10 P11 遠隔保守契約 service 0.670
4 P05 省エネモーター motor 0.500
1 P02 高精度センサー sensor 0.314

結果の読み取り

上位候補は『同等品』ではなく、仕様空間で近い候補です。互換性、安全規格、設備接続条件は別途ルールで絞り込みます。類似検索は営業の探索範囲を広げ、最終判断は技術担当が行う設計が安全です。

No.087:類似顧客を検索する

実務での意味

新規顧客や担当変更時に、似た既存顧客の導入事例を参照できれば、初回提案の仮説を短時間で作れます。

分析・モデル化の考え方

標準化した顧客特徴量のユークリッド距離を使います。購買履歴そのものではなく経営・設備特性が似た顧客を探すため、後の協調フィルタリングとは異なる根拠の推薦になります。

Pythonで確認する

query_customer = "C050"
q = customers.index[customers.customer_id == query_customer][0]
dist = np.linalg.norm(X - X[q], axis=1)
nearest = np.argsort(dist)[1:6]
similar_customers = customers.loc[nearest, ["customer_id", "cluster"] + feature_cols].copy()
similar_customers.insert(2, "distance", dist[nearest])
print("検索元")
display(customers.loc[[q], ["customer_id", "cluster"] + feature_cols].round(2))
print("近い顧客")
similar_customers.round(2)
検索元
customer_id cluster annual_purchase_mjpy installed_machines preventive_ratio quality_requirement downtime_loss_mjpy
49 C050 0 53.26 24.32 0.76 91.24 3.33
近い顧客
customer_id cluster distance annual_purchase_mjpy installed_machines preventive_ratio quality_requirement downtime_loss_mjpy
46 C047 0 1.04 50.98 27.87 0.61 77.65 3.77
67 C068 0 1.15 54.18 27.30 0.61 77.24 5.11
54 C055 0 1.25 60.62 34.22 0.57 84.75 6.07
56 C057 0 1.29 76.24 19.79 0.67 71.64 3.39
61 C062 0 1.37 56.31 29.66 0.71 72.66 6.23

結果の読み取り

距離が近い顧客の成功事例は提案仮説になりますが、契約条件や業界規制が同じとは限りません。検索結果には『似ている根拠となった特徴量』も併記し、営業が説明できる状態にします。

No.088:ユーザー×アイテム行列を作る

実務での意味

推薦の入力となる購買履歴を、顧客を行、製品を列にした行列へ変換します。基幹データの粒度・重複・返品処理を決める実務上の重要工程です。

分析・モデル化の考え方

今回は購入ありを1、なしを0とする暗黙的フィードバックを使います。0は低評価ではなく未観測です。購入数量や金額を使う場合は、大口顧客だけが距離を支配しない変換が必要です。

Pythonで確認する

matrix_preview = purchase_df.iloc[:10].copy()
matrix_preview["purchased_items"] = matrix_preview.sum(axis=1)
matrix_preview
product_id P01 P02 P03 P04 P05 P06 P07 P08 P09 P10 P11 P12 purchased_items
customer_id
C001 1 0 0 0 0 0 0 1 0 1 1 0 4
C002 1 1 0 1 0 0 0 0 0 0 0 1 4
C003 0 0 1 0 1 0 1 1 1 0 0 1 6
C004 1 1 0 0 0 0 1 1 1 0 0 0 5
C005 0 0 1 0 0 0 0 0 0 0 1 0 2
C006 1 0 0 1 0 1 0 0 0 0 1 1 5
C007 0 1 0 0 0 0 0 0 0 0 0 0 1
C008 0 1 0 1 0 0 0 0 1 0 0 0 3
C009 0 1 0 1 0 0 1 0 1 0 0 1 5
C010 0 0 1 0 0 0 1 0 0 1 0 0 3

結果の読み取り

行列は多くが0になる疎行列です。密度、購入ゼロ顧客、購入ゼロ製品を監視します。閲覧や見積履歴も統合すれば情報は増えますが、行動ごとの重みと個人情報・契約上の利用目的を定義する必要があります。

No.089:協調フィルタリングを実装する

実務での意味

似た購買パターンの顧客が購入した製品を候補にすることで、属性データだけでは見えないクロスセル機会を発見します。

分析・モデル化の考え方

顧客間コサイン類似度を wuvw_{uv}、顧客 vv の製品 ii 購買を rvir_{vi} とし、r^ui=vwuvrvi/vwuv\hat r_{ui}=\sum_v w_{uv}r_{vi}/\sum_v|w_{uv}| でスコア化します。既購入品は候補から除外します。

Pythonで確認する

def recommend_user_based(matrix, customer_id, k=5, neighbor_n=15):
    sim = cosine_similarity(matrix)
    u = matrix.index.get_loc(customer_id)
    neighbors = np.argsort(sim[u])[::-1]
    neighbors = neighbors[(neighbors != u)][:neighbor_n]
    weights = sim[u, neighbors]
    scores = weights @ matrix.iloc[neighbors].to_numpy() / (np.abs(weights).sum() + 1e-12)
    scores[matrix.iloc[u].to_numpy() > 0] = -np.inf
    top = np.argsort(scores)[::-1][:k]
    result = products.set_index("product_id").loc[matrix.columns[top], ["product_name", "category"]].copy()
    result["recommendation_score"] = scores[top]
    return result

recommend_user_based(purchase_df, "C050", k=5).round(3)
product_name category recommendation_score
product_id
P08 予知保全端末 digital 0.511
P05 省エネモーター motor 0.439
P12 省エネ診断 service 0.421
P10 交換部品キット service 0.377
P07 簡易監視端末 digital 0.337

結果の読み取り

スコアは購買確率そのものではなく順位付けの指標です。推薦理由として、近傍顧客数や類似事例を提示します。新規顧客・新製品には履歴がないコールドスタートがあるため、No.086・087の属性ベース候補と併用します。

No.090:推薦結果をPrecision@K・Recall@Kで評価する

実務での意味

推薦を導入する前に、過去の一部購入を隠し、上位K件で再発見できるかを測ります。営業接触枠が有限ならPrecision、機会損失を避けたいならRecallを重視します。

分析・モデル化の考え方

顧客 uu の上位K集合を Ru@KR_u@K、テスト期間の購入集合を TuT_u とすると、Precision@K=Ru@KTu/K\mathrm{Precision@K}=|R_u@K\cap T_u|/KRecall@K=Ru@KTu/Tu\mathrm{Recall@K}=|R_u@K\cap T_u|/|T_u| です。

Pythonで確認する

def offline_evaluate(matrix, k=3, seed=42):
    local_rng = np.random.default_rng(seed)
    train = matrix.copy()
    heldout = {}
    for cid in matrix.index:
        bought = np.flatnonzero(matrix.loc[cid].to_numpy())
        if len(bought) >= 2:
            test_i = int(local_rng.choice(bought))
            train.iloc[train.index.get_loc(cid), test_i] = 0
            heldout[cid] = matrix.columns[test_i]
    sim = cosine_similarity(train)
    precisions, recalls = [], []
    for cid, true_item in heldout.items():
        u = train.index.get_loc(cid)
        neighbors = np.argsort(sim[u])[::-1]
        neighbors = neighbors[(neighbors != u)][:15]
        w = sim[u, neighbors]
        scores = w @ train.iloc[neighbors].to_numpy() / (np.abs(w).sum() + 1e-12)
        scores[train.iloc[u].to_numpy() > 0] = -np.inf
        recs = set(train.columns[np.argsort(scores)[::-1][:k]])
        hit = int(true_item in recs)
        precisions.append(hit / k)
        recalls.append(hit)  # held-out item is one item
    return len(heldout), np.mean(precisions), np.mean(recalls)

rows = []
for k in [1, 3, 5]:
    n, precision, recall = offline_evaluate(purchase_df, k=k)
    rows.append((k, n, precision, recall))
evaluation = pd.DataFrame(rows, columns=["K", "evaluated_customers", "Precision@K", "Recall@K"])
evaluation.round(3)
K evaluated_customers Precision@K Recall@K
0 1 118 0.169 0.169
1 3 118 0.144 0.432
2 5 118 0.132 0.661

結果の読み取り

Kを増やすと一般にRecallは上がりやすく、Precisionは下がりやすくなります。今回の単純なランダム保留は学習用デモです。実務では時点で分割し、人気順推薦や現行営業ルールをベースラインにして、最終的に商談化率・粗利・解約抑制をA/Bテストします。

7. 対象ノックを通して見える実務上の示唆

  1. セグメントと推薦は役割が違う:クラスタは施策設計の単位、推薦は顧客ごとの候補順位です。両方をつなぐと、全体施策と個別提案を両立できます。
  2. 類似性を一つに固定しない:設備・経営特性、製品仕様、購買パターンは異なる証拠です。複数の候補を統合し、根拠を表示する方が実務で信頼されます。
  3. 未購入を拒否とみなさない:購買0には未提案、他社購入、更新時期前などが混在します。商談履歴や設備適合条件を加える必要があります。
  4. 評価指標を営業能力と結ぶ:Kはモデル都合ではなく、1担当者が確認・接触できる候補数から決めます。

8. 実務導入する場合に必要なこと

  • データ定義:顧客・製品の名寄せ、返品・無償品の扱い、購買時点、廃番・互換情報を管理する
  • 安全な候補生成:設備互換、安全規格、供給可否、契約制約をルールで先に除外する
  • 時間軸を守る検証:未来情報の混入を防ぎ、過去で学習して将来購買を評価する
  • 現場運用:CRMへ候補、根拠、除外理由、フィードバック入力欄を実装する
  • KPI設計:Precision@Kだけでなく、採用率、商談化率、粗利、顧客満足、推薦の偏りを監視する
  • ガバナンス:利用目的、アクセス権、保存期間、モデル更新責任、停止基準を定める

小規模な導入では、まず1営業チーム・1製品群で、月次の候補リストと人手レビューから始めると効果とリスクを確認しやすくなります。

9. まとめ

No.081〜090では、顧客の構造をクラスタリングで理解し、PCAで説明し、類似検索と協調フィルタリングで提案候補を作り、Precision@K・Recall@Kで評価しました。重要なのは高度なアルゴリズムよりも、類似性の定義、業務制約、時間を守った評価、営業が説明できる推薦理由です。

10. 法人向けのご相談

数理工房では、製造業における顧客セグメント設計、類似製品検索、クロスセル推薦、PoC評価設計から業務実装までご相談いただけます。保有データの棚卸しや、既存の営業ルールをベースラインにした小規模検証からでも対応可能です。

📩 お問い合わせ: surikobo.co.jp/contact
まずはお気軽にご相談ください。