
K近傍法(KNN)で品質管理
K近傍法とは?
K近傍法(K-Nearest Neighbors, KNN)は、シンプルかつ直感的な機械学習のアルゴリズムの一つです。
このアルゴリズムでは、新しいデータポイントの分類や予測を、その周囲の「近くにあるデータポイント(近傍)」を使って行います。
この特徴を活かして、品質管理の現場で大きな力を発揮します。
では具体例を見ながら、KNNの理解を深めていきましょう。
例: 電子部品の検査
例えば、ある工場で製造される電子部品の品質を管理するとします。
各部品には次のような特徴があります:
長さ(ミリメートル)
幅(ミリメートル)
厚さ(ミリメートル)
重量(グラム)
これらの特徴に基づいて、部品が「高品質」なのか「低品質」なのかを分類してみましょう。
1. データの収集
まず、既知の部品のデータから、どれが高品質でどれが低品質かを特定しましょう。
そのためには過去データを品質で分類する必要があります。
そのために各部品の特徴(長さ、幅、厚さ、重量)と品質ラベル(高品質、低品質)などのデータを集めます。
サンプルデータ

2. 新しい部品の評価
次に、新しく製造された部品のデータを評価します。
この部品の特徴データ(長さ、幅、厚さ、重量)を使って、過去データをもとにその品質を予測します。
新しい部品のデータ

3. 距離の計算
新しい部品と既知の部品データとの距離を計算します。
ここでいう距離は、数学的な距離(例えばユークリッド距離)です。
4. 近傍の選択
計算した距離に基づいて、新しい部品に最も近いK個の既知の部品を選びます。例えば、K=3とします。
例: 近傍の部品

5. 多数決による予測
選ばれた近傍の部品の品質ラベルを見て、多数決で新しい部品の品質を予測します。ここでは、3つの近傍のうち2つが「高品質」、1つが「低品質」なので、新しい部品は「高品質」と予測されます。
Kの値を選ぶ
Kが小さすぎるとモデルが敏感になりすぎてしまい、ノイズが大きくなります(過学習のリスク)。
一方でKが大きいとモデルが全体の傾向に偏りすぎてしまい、パターンの機微を見逃すことがあります(過小適合のリスク)。
一般的にKの値は、多数決で同数になることを避けるため奇数で設定します。
以下に、Kの値を決めるための一般的な方法を紹介します。
交差検証(Cross-Validation)
交差検証は、データセットを複数の部分に分割し、それぞれをテストデータとして交互に使用しながらモデルを評価する方法です。
データセットを複数の部分に分割(例:5分割)。
それぞれの部分を順番にテストデータとして使用し、残りの部分を訓練データとして使用。
各Kの値に対して、全てのテストデータでの精度を計算。
平均精度が最も高いKの値を選ぶ。
グリッドサーチ(Grid Search)
グリッドサーチは、複数のKの値を試し、その中で最も良い性能を示すKの値を選ぶ方法です。
複数のKの値(例:1から20まで)を試す。
各Kの値に対してモデルを訓練し、テストデータでの精度を計算。
最も高い精度を示したKの値を選ぶ。
KNNの長所
シンプルで理解しやすい:
複雑な計算や前提知識がほとんど不要で、直感的に理解しやすいです。トレーニングが不要:
新しいデータポイントに対して直接計算を行うため、事前のトレーニングが不要です(遅延学習)。
KNNの短所
計算量が多い:
新しいデータポイントが来るたびに全てのデータポイントとの距離を計算するため、データが大きいと計算量が増えます。特徴量のスケーリングが必要:
特徴量のスケールが異なる場合、距離計算に影響を与えるため、正規化や標準化が必要です。
ぜひ現場で利用しよう
KNNを使うことで、あなたの職場でも、既知のデータに基づいて簡単に品質予測ができます。
機械学習を化け物として恐れるのではなく、ぜひ味方につけて業務の効率化と品質向上をめざしましょう。
実際のプログラム
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
解説: ここでは、必要なライブラリをインポートしています。
numpy(np)は数値計算のためのライブラリです。
pandas(pd)はデータ操作のためのライブラリです。
train_test_splitはデータを訓練用とテスト用に分割するための関数です。
GridSearchCVはグリッドサーチを使って最適なパラメータを見つけるためのクラスです。
KNeighborsClassifierはK近傍法のモデルを作成するためのクラスです。
accuracy_scoreはモデルの精度を計算するための関数です。
def create_synthetic_data(n_samples=1000):
np.random.seed(42)
length = np.random.normal(loc=10, scale=1, size=n_samples)
width = np.random.normal(loc=5, scale=0.5, size=n_samples)
thickness = np.random.normal(loc=2, scale=0.2, size=n_samples)
weight = np.random.normal(loc=0.8, scale=0.1, size=n_samples)
quality = np.where((length > 9.5) & (length < 10.5) &
(width > 4.5) & (width < 5.5) &
(thickness > 1.8) & (thickness < 2.2) &
(weight > 0.7) & (weight < 0.9), 1, 0)
data = pd.DataFrame({
'Length': length,
'Width': width,
'Thickness': thickness,
'Weight': weight,
'Quality': quality
})
return data
解説: この関数では、電子部品のデータを大量生成します。
np.random.seed(42)とすることで、同じ乱数が発生します。
np.random.normal(loc=..., scale=..., size=...)は指定された
平均値(loc)
標準偏差(scale)
サイズ(size)
などに基づいて正規分布に従う乱数を生成します。np.whereは条件に基づいて品質ラベル(0: 低品質, 1: 高品質)を設定します。
最後に、これらのデータをDataFrameにまとめて返します。
python
data = create_synthetic_data(n_samples=1000)
解説: 先ほど定義したcreate_synthetic_data関数を使って、1000個のサンプルデータを生成しています。
こんな感じのデータが出来上がります。

X = data[['Length', 'Width', 'Thickness', 'Weight']]
y = data['Quality']
解説: データを特徴量(長さ、幅、厚さ、重量)とターゲット変数(品質)に分けています。
Xは特徴量のデータです。
yはターゲット変数(品質ラベル)のデータです。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
解説: データを訓練セットとテストセットに分割しています。
test_size=0.3はデータの30%をテスト用にすることを意味します。
random_state=42は結果を再現可能にするための設定です。
param_grid = {'n_neighbors': range(1, 21)}
knn = KNeighborsClassifier()
grid_search = GridSearchCV(knn, param_grid, cv=5, scoring='accuracy')
解説: グリッドサーチの設定を行っています。
param_gridは試すべきKの値の範囲を設定しています(ここでは1から20まで)。
knnはK近傍法のモデルです。
grid_searchで、グリッドサーチを行うための設定を行います。
ここでは5つの分割(cv=5)で交差検証を行い、精度を評価します。
grid_search.fit(X_train, y_train)
解説: グリッドサーチを実行し、最適なKの値を見つけるために訓練データを使ってモデルを訓練しています。
best_k = grid_search.best_params_['n_neighbors']
best_score = grid_search.best_score_
print(f'最適なKの値: {best_k}')
print(f'クロスバリデーションの精度: {best_score:.2f}')
解説: グリッドサーチで見つけた最適なKの値とその時の精度を出力しています。
best_kは最適なKの値です。
best_scoreは最適なKの値でのクロスバリデーション精度です。
最適なKの値: 4
クロスバリデーションの精度: 0.94
と出ました。
model = KNeighborsClassifier(n_neighbors=best_k)
model.fit(X_train, y_train)
解説: 最適なKの値を使ってK近傍法のモデルを再度作成し、訓練データを使ってモデルを学習させています。
y_pred = model.predict(X_test)
解説: 学習したモデルを使って、テストデータの予測を行っています。
y_predはテストデータに対する予測結果です。
accuracy = accuracy_score(y_test, y_pred)
print(f'テストセットの精度: {accuracy:.2f}')
解説: 予測結果の精度を計算し、テストデータに対するモデルの精度を出力しています。
accuracyは精度です。
テストセットの精度: 0.94
と出ました。
new_data = [[10.4, 5.1, 2.0, 0.75]]
解説: 新しい部品のデータを定義しています。順に、長さ、幅、厚さ、重量です。
prediction = model.predict(new_data)
predicted_class = "高品質" if prediction[0] == 1 else "低品質"
print(f'新しいデータの予測品質: {predicted_class}')
解説: 新しいデータを使って、その品質を予測しています。
predictionは新しいデータに対する予測結果です。
predicted_classに高品質または低品質という日本語を格納します。
新しいデータの予測品質: 高品質
と出ました。
プログラムの全体像
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# データの生成
def create_synthetic_data(n_samples=1000):
np.random.seed(42)
length = np.random.normal(loc=10, scale=1, size=n_samples) # 長さ
width = np.random.normal(loc=5, scale=0.5, size=n_samples) # 幅
thickness = np.random.normal(loc=2, scale=0.2, size=n_samples) # 厚さ
weight = np.random.normal(loc=0.8, scale=0.1, size=n_samples) # 重量
# 品質ラベル(0: 低品質, 1: 高品質)
quality = np.where((length > 9.5) & (length < 10.5) &
(width > 4.5) & (width < 5.5) &
(thickness > 1.8) & (thickness < 2.2) &
(weight > 0.7) & (weight < 0.9), 1, 0)
data = pd.DataFrame({
'Length': length,
'Width': width,
'Thickness': thickness,
'Weight': weight,
'Quality': quality
})
return data
# データの生成
data = create_synthetic_data(n_samples=1000)
# 特徴量とターゲット変数の分割
X = data[['Length', 'Width', 'Thickness', 'Weight']]
y = data['Quality']
# データを訓練セットとテストセットに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# グリッドサーチの設定
param_grid = {'n_neighbors': range(1, 21)}
knn = KNeighborsClassifier()
grid_search = GridSearchCV(knn, param_grid, cv=5, scoring='accuracy')
# グリッドサーチの実行
grid_search.fit(X_train, y_train)
# 最適なKの値と精度を出力
best_k = grid_search.best_params_['n_neighbors']
best_score = grid_search.best_score_
print(f'最適なKの値: {best_k}')
print(f'クロスバリデーションの精度: {best_score:.2f}')
# 最適なKを使ってモデルを再度学習
model = KNeighborsClassifier(n_neighbors=best_k)
model.fit(X_train, y_train)
# テストセットで予測
y_pred = model.predict(X_test)
# 精度の計算
accuracy = accuracy_score(y_test, y_pred)
print(f'テストセットの精度: {accuracy:.2f}')
# 新しいデータで予測
new_data = [[10.4, 5.1, 2.0, 0.75]] # 新しい部品のデータ
prediction = model.predict(new_data)
predicted_class = "高品質" if prediction[0] == 1 else "低品質"
print(f'新しいデータの予測品質: {predicted_class}')