見出し画像

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)

交差検証は、データセットを複数の部分に分割し、それぞれをテストデータとして交互に使用しながらモデルを評価する方法です。

  1. データセットを複数の部分に分割(例:5分割)。

  2. それぞれの部分を順番にテストデータとして使用し、残りの部分を訓練データとして使用。

  3. 各Kの値に対して、全てのテストデータでの精度を計算。

  4. 平均精度が最も高いKの値を選ぶ。

グリッドサーチ(Grid Search)

グリッドサーチは、複数のKの値を試し、その中で最も良い性能を示すKの値を選ぶ方法です。

  1. 複数のKの値(例:1から20まで)を試す。

  2. 各Kの値に対してモデルを訓練し、テストデータでの精度を計算。

  3. 最も高い精度を示したKの値を選ぶ。

KNNの長所

  1. シンプルで理解しやすい:
    複雑な計算や前提知識がほとんど不要で、直感的に理解しやすいです。

  2. トレーニングが不要:
    新しいデータポイントに対して直接計算を行うため、事前のトレーニングが不要です(遅延学習)。

KNNの短所

  1. 計算量が多い:
    新しいデータポイントが来るたびに全てのデータポイントとの距離を計算するため、データが大きいと計算量が増えます。

  2. 特徴量のスケーリングが必要:
    特徴量のスケールが異なる場合、距離計算に影響を与えるため、正規化や標準化が必要です。

ぜひ現場で利用しよう

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}')




いいなと思ったら応援しよう!