グラフデータセットの構築と前処理
金融貸付リスク予測には、借り手間の関係性をグラフ構造で表現することが効果的です。グラフニューラルネットワーク(GNN)を適用するためには、適切なデータ形式への変換が必要となります。
データ構造の設計
借り手情報と貸付関係を表すCSVファイルの例:
借り手ノードデータ (borrower_nodes.csv)
node_id,credit_score,income_level,debt_ratio,default_flag
1,0.65,0.82,0.45,0
2,0.72,0.63,0.38,1
3,0.58,0.75,0.52,0
...
貸付エッジデータ (loan_edges.csv)
source_node,target_node,loan_value,loan_period
1,2,12000,18
2,3,8000,12
3,1,15000,24
...
データ読み込みと変換
import pandas as pd
import torch
from torch_geometric.data import Data
# ノード特徴量の読み込み
node_data = pd.read_csv('borrower_nodes.csv')
node_features = node_data[['credit_score', 'income_level', 'debt_ratio']].values
node_labels = node_data['default_flag'].values
# エッジ情報の読み込み
edge_data = pd.read_csv('loan_edges.csv')
edge_index = torch.tensor([
edge_data['source_node'].tolist(),
edge_data['target_node'].tolist()
], dtype=torch.long)
# グラフデータオブジェクトの作成
graph_data = Data(
x=torch.tensor(node_features, dtype=torch.float),
edge_index=edge_index,
y=torch.tensor(node_labels, dtype=torch.long)
)
注意機構付きGNNモデルの実装
import torch.nn as nn
from torch_geometric.nn import MessagePassing
from torch_geometric.utils import add_self_loops, degree
class AttentiveGraphLayer(MessagePassing):
def __init__(self, input_dim, output_dim):
super().__init__(aggr='mean')
self.feature_transform = nn.Linear(input_dim, output_dim)
self.attention_net = nn.Linear(2 * output_dim, 1)
def forward(self, features, edge_indices, edge_weights=None):
# 自己ループの追加
edge_indices, edge_weights = add_self_loops(
edge_indices, edge_weights, num_nodes=features.size(0)
)
# 特徴量変換
transformed_features = self.feature_transform(features)
# 正規化係数の計算
source_nodes, target_nodes = edge_indices
node_degrees = degree(source_nodes, features.size(0), dtype=features.dtype)
normalized_weights = node_degrees.pow(-0.5)
normalization = normalized_weights[source_nodes] * edge_weights * normalized_weights[target_nodes]
return self.propagate(
edge_indices,
x=transformed_features,
norm_factor=normalization
)
def message(self, x_j, norm_factor):
# 注意係数の計算
attention_input = torch.cat([x_j, x_j], dim=-1)
attention_scores = self.attention_net(attention_input)
weighted_scores = attention_scores * norm_factor.view(-1, 1)
# 重みの適用
return nn.functional.softmax(weighted_scores, dim=1) * x_j
class RiskPredictionGNN(nn.Module):
def __init__(self, feature_size, num_classes):
super().__init__()
self.layer1 = AttentiveGraphLayer(feature_size, 32)
self.layer2 = AttentiveGraphLayer(32, num_classes)
def forward(self, features, edge_indices, edge_weights=None):
hidden = self.layer1(features, edge_indices, edge_weights)
hidden = nn.functional.relu(hidden)
hidden = nn.functional.dropout(hidden, training=self.training)
output = self.layer2(hidden, edge_indices, edge_weights)
return nn.functional.log_softmax(output, dim=1)
モデル訓練と評価
import torch.optim as optim
# デバイスの設定
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = RiskPredictionGNN(feature_size=3, num_classes=2).to(device)
training_data = graph_data.to(device)
# 最適化の設定
optimizer = optim.Adam(model.parameters(), lr=0.005, weight_decay=1e-4)
# 訓練ループ
model.train()
for epoch in range(150):
optimizer.zero_grad()
predictions = model(training_data.x, training_data.edge_index)
loss = nn.functional.nll_loss(predictions, training_data.y)
loss.backward()
optimizer.step()
予測の実行
model.eval()
with torch.no_grad():
test_predictions = model(test_data.x, test_data.edge_index)
probability_scores = nn.functional.softmax(test_predictions, dim=1)
# デフォルト確率の抽出(クラス1に対応)
default_probabilities = probability_scores[:, 1]
# 閾値による分類
risk_threshold = 0.6
high_risk_flags = default_probabilities > risk_threshold
この実装では、借り手間の貸付関係をグラフ構造として捉え、注意機構を組み込んだGNNモデルによって信用リスクを評価します。特徴量の変換と関係性の重み付けを同時に学習することで、従来の機械学習手法よりも精度の高いリスク予測が可能となります。