Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで実現するクレジットカード不正検出:機械学習による実装ガイド


クレジットカード取引をはじめとする大量の取引データには、不正(Fraud)が潜んでいます。機械学習アルゴリズムを活用すれば、過去のデータを学習させ、新しい取引が不正である可能性を予測できます。

本記事では、Kaggleで公開されているクレジットカード取引データセットを題材に、データの分析から特徴量とラベルの作成、機械学習モデルの構築までを段階的に解説します。最後に、モデルの精度(Accuracy)、適合率(Precision)、再現率(Recall)、F値(F-score)を算出して評価します。

1. データの準備

最初のステップでは、ソースデータを読み込み、含まれる変数を把握し、サンプルデータを目視確認します。これにより、データセットに存在する各カラムとその特性を理解できます。Pandasライブラリを使ってデータフレームを作成し、以降の処理に活用していきます。

コード例

import pandas as pd
# pandasを使ってcreditcard.csvを読み込む
datainput = pd.read_csv('E:\creditcard.csv')
# https://www.kaggle.com/mlg-ulb/creditcardfraud

# 先頭5件のレコードを出力
print(datainput[0:5],"\n")

# データセット全体の形状を出力
print("Shape of Complete Data Set")
print(datainput.shape,"\n")

実行結果

     Time        V1            V2            V3    ...          V27         V28   Amount      Class
0    0.0 -1.359807    -0.072781     2.536347    ...     0.133558   -0.021053   149.62          0
1    0.0  1.191857     0.266151     0.166480    ...    -0.008983    0.014724     2.69          0
2    1.0 -1.358354    -1.340163     1.773209    ...    -0.055353   -0.059752   378.66          0
3    1.0 -0.966272    -0.185226     1.792993    ...     0.062723    0.061458   123.50          0
4    2.0 -1.158233     0.877737     1.548718    ...     0.219422    0.215153    69.99          0

[5 rows x 31 columns]
Shape of Complete Data Set
(284807, 31)

データセットは284,807行×31列で構成されており、V1〜V28は主成分分析(PCA)によって変換された匿名化された特徴量、Amountは取引金額、Classは正解ラベル(0=正常、1=不正)を表しています。

2. データの不均衡の確認

次に、不正取引と正当な取引がどのように分布しているかを確認します。これにより、データ全体に占める不正取引の割合を把握できます。機械学習において、この偏りは「データの不均衡」と呼ばれます。

大多数の取引が正常である場合、少数派である不正取引を見抜くのは非常に困難になります。そこでClass列を使って不正取引の件数を数え、実際の割合を算出してみましょう。

コード例

import pandas as pd
# pandasを使ってcreditcard.csvを読み込む
datainput = pd.read_csv('E:\creditcard.csv')

false = datainput[datainput['Class'] == 1]
true = datainput[datainput['Class'] == 0]
n = len(false)/float(len(true))
print(n)
print('False Detection Cases: {}'.format(len(datainput[datainput['Class'] == 1])))
print('True Detection Cases: {}'.format(len(datainput[datainput['Class'] == 0])),"\n")

実行結果

0.0017304750013189597
False Detection Cases: 492
True Detection Cases: 284315

全284,807件のうち不正取引はわずか492件(約0.17%)しかありません。このような極端な不均衡データに対しては、単純な精度評価だけではモデルの性能を正しく判断できない点に注意が必要です。

3. 取引タイプごとの統計詳細

不正取引と正常取引のそれぞれについて、取引金額などの性質をさらに詳しく調べます。平均、標準偏差、最大値、最小値、各種パーセンタイルといった統計量を推定しましょう。これにはdescribe()メソッドが便利です。

コード例

import pandas as pd
# pandasを使ってcreditcard.csvを読み込む
datainput = pd.read_csv('E:\creditcard.csv')

# データの不均衡を確認
false = datainput[datainput['Class'] == 1]
true = datainput[datainput['Class'] == 0]

# 不正取引(False Detection Cases)
print("False Detection Cases")
print("----------------------")
print(false.Amount.describe(),"\n")

# 正常取引(True Detection Cases)
print("True Detection Cases")
print("----------------------")
print(true.Amount.describe(),"\n")

実行結果

False Detection Cases
----------------------
count     492.000000
mean      122.211321
std       256.683288
min         0.000000
25%         1.000000
50%         9.250000
75%       105.890000
max      2125.870000
Name: Amount, dtype: float64

True Detection Cases
----------------------
count    284315.000000
mean         88.291022
std         250.105092
min           0.000000
25%           5.650000
50%          22.000000
75%          77.050000
max        25691.160000
Name: Amount, dtype: float64

興味深いことに、不正取引の平均金額(約122ドル)は正常取引(約88ドル)より高く、中央値も9.25ドル対22ドルと傾向が異なります。こうした統計的な違いは、特徴量エンジニアリングのヒントになります。

4. 特徴量とラベルの分離

機械学習アルゴリズムを実装する前に、特徴量(説明変数)とラベル(目的変数)を決定する必要があります。つまり、従属変数と独立変数を分類するということです。

このデータセットでは、Class列がそれ以外のすべての列に依存すると考えられるため、最終列をラベル(y)とするデータフレームと、残りの列を特徴量(X)とするデータフレームに分割します。これらはモデルの学習に使用されます。

コード例

import pandas as pd
# pandasを使ってcreditcard.csvを読み込む
datainput = pd.read_csv('E:\creditcard.csv')

# 特徴量(X)とラベル(y)を分離
# 最終列以外のすべての列を選択
X = datainput.iloc[:, :-1].values
# 全行の最終列を選択
Y = datainput.iloc[:, -1].values

print(X.shape)
print(Y.shape)

実行結果

(284807, 30)
(284807,)

5. モデルの学習

続いて、データセットを学習用とテスト用の2つに分割します。train_test_split()のtest_sizeパラメータを使うと、データセットのうち何割をテスト専用に使うかを指定できます。ここでは20%(0.2)をテストデータとして確保します。この分割により、未知のデータに対するモデルの信頼性を検証できます。

コード例

import pandas as pd
from sklearn.model_selection import train_test_split

# pandasを使ってcreditcard.csvを読み込む
datainput = pd.read_csv('E:\creditcard.csv')

# 特徴量(X)とラベル(y)を分離
X = datainput.iloc[:, :-1].values
Y = datainput.iloc[:, -1].values

# train_test_splitメソッドで分割
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

6. 決定木分類の適用

分類タスクに使えるアルゴリズムは多数ありますが、ここでは決定木(Decision Tree)を採用します。木の最大深度を4に設定してモデルを作成し、テストデータを与えて予測値を求めます。最後にテスト結果の精度を計算し、このアルゴリズムを採用すべきかどうかを判断します。

コード例

import pandas as pd
from sklearn import metrics
from sklearn.model_selection import train_test_split

# pandasを使ってcreditcard.csvを読み込む
datainput = pd.read_csv('E:\creditcard.csv')

# 特徴量(X)とラベル(y)を分離
X = datainput.iloc[:, :-1].values
Y = datainput.iloc[:, -1].values

# train_test_splitメソッドで分割
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

# 決定木分類器(DecisionTreeClassifier)
from sklearn.tree import DecisionTreeClassifier
classifier=DecisionTreeClassifier(max_depth=4)
classifier.fit(X_train,Y_train)
predicted=classifier.predict(X_test)
print("\npredicted values :\n",predicted)

# 精度(Accuracy)
DT = metrics.accuracy_score(Y_test, predicted) * 100
print("\nThe accuracy score using the DecisionTreeClassifier : ",DT)

実行結果

predicted values :
[0 0 0 ... 0 0 0]
The accuracy score using the DecisionTreeClassifier : 99.9367999719111

一見すると99.93%という非常に高い精度に見えますが、前述のとおり正常取引が99.8%以上を占めるため、「すべてを正常と予測しても高い精度になる」という罠があります。そのため、以下のような追加の評価指標が不可欠です。

7. 評価指標の算出

上記ステップの精度が許容範囲であれば、さまざまな指標を用いてモデルをさらに評価します。ここでは適合率(Precision)、再現率(Recall)、F値(F-score)を使用します。

  • 適合率(Precision): 不正と予測したもののうち、実際に不正だった割合。誤検知(偽陽性)の少なさを測る指標です。
  • 再現率(Recall): 実際の不正のうち、正しく不正と検出できた割合。見逃し(偽陰性)の少なさを測る指標です。
  • F値(F-score): 適合率と再現率の調和平均であり、両者のバランスを1つの数値で表します。

コード例

import pandas as pd
from sklearn import metrics
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score

# pandasを使ってcreditcard.csvを読み込む
datainput = pd.read_csv('E:\creditcard.csv')

# 特徴量(X)とラベル(y)を分離
X = datainput.iloc[:, :-1].values
Y = datainput.iloc[:, -1].values

# train_test_splitメソッドで分割
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

# 決定木分類器(DecisionTreeClassifier)
from sklearn.tree import DecisionTreeClassifier
classifier=DecisionTreeClassifier(max_depth=4)
classifier.fit(X_train,Y_train)
predicted=classifier.predict(X_test)
print("\npredicted values :\n",predicted)

# 精度(Accuracy)
DT = metrics.accuracy_score(Y_test, predicted) * 100
print("\nThe accuracy score using the DecisionTreeClassifier : ",DT)

# 適合率(Precision)
# Precision = TP / (TP + FP)(TP=真陽性、FP=偽陽性)
print('precision')
precision = precision_score(Y_test, predicted, pos_label=1)
print(precision_score(Y_test, predicted, pos_label=1))

# 再現率(Recall)
# Recall = TP / (TP + FN)(FN=偽陰性)
print('recall')
recall = recall_score(Y_test, predicted, pos_label=1)
print(recall_score(Y_test, predicted, pos_label=1))

# F値(F1-score)
# 適合率と再現率の両方を考慮した精度指標
print('f-Score')
fscore = f1_score(Y_test, predicted, pos_label=1)
print(f1_score(Y_test, predicted, pos_label=1))

実行結果

The accuracy score using the DecisionTreeClassifier : 99.9403110845827
precision
0.810126582278481
recall
0.7710843373493976
f-Score
0.7901234567901234

まとめと改善のポイント

本記事では、Pythonとscikit-learnを使ってクレジットカード不正検出モデルを構築する一連の流れを紹介しました。精度は99.9%超ですが、適合率81%、再現率77%、F値79%という結果から、不均衡データ特有の課題が浮き彫りになります。

さらなる改善のためには、以下の手法が有効です。

  • オーバーサンプリング/アンダーサンプリング: SMOTEなどの手法で少数派クラスを水増しする、または多数派クラスを削減してバランスを取ります。
  • クラス重みの付与: DecisionTreeClassifierのclass_weight='balanced'パラメータで不均衡を補正できます。
  • 異なるアルゴリズムの比較: ランダムフォレストや勾配ブースティング(XGBoost、LightGBMなど)は不均衡データに強い傾向があります。
  • 交差検証の導入: StratifiedKFoldを使えば、クラス比率を保ったまま安定した評価が可能です。

不正検出は「見逃しのコスト」が非常に大きい領域です。単なる精度だけでなく、再現率やF値を総合的に評価しながら、ビジネス要件に合ったモデルを追求していきましょう。

  1. Pythonで顧客離反(チャーン)を予測する方法:機械学習による実践ガイド

    あらゆるビジネスは顧客のロイヤルティに依存しています。リピート購入は企業の収益性を支える重要な柱の一つであり、顧客が離れていく理由を把握することは極めて重要です。このように顧客が離反していく現象は「カスタマーチャーン(Customer Churn)」と呼ばれます。過去の傾向を分析することで、どのような要因が顧客離反に影響を与えているのかを把握し、特定の顧客が離反するかどうかを予測できるようになります。本記事では、機械学習アルゴリズムを使って過去の顧客離反データの傾向を分析し、どの顧客が離反する可能性が高いかを判定する方法を解説します。データの準備例として、通信業界(Telecom)の顧客離反デ

  2. Pythonで国勢調査データを分析する方法|インドの人口統計データを可視化してみよう

    国勢調査(センサス)とは、特定の対象人口に関する情報を体系的に記録・収集する取り組みです。収集されるデータには、人口統計、経済状況、居住環境など、さまざまなカテゴリの情報が含まれています。これらのデータは、政府が現状を正確に把握し、将来に向けた政策立案を行ううえで重要な基礎資料となります。本記事では、Pythonを活用してインドの国勢調査データを分析する方法を解説します。人口動態や経済指標など複数の観点からデータを掘り下げ、その結果をグラフとして視覚的に表現します。使用するデータセットはKaggleから入手した「India Districts Census 2011」です。データの準備と読み込