多层感知机
1.案例描述
构建一个多层感知机,用于二分类。其中,超参数用贝叶斯优化器,数据生借助scikit-learn实现。
2.代码实现
# -*- coding:utf-8 -*- import torch import torch.nn as nn import torch.optim as optim import numpy as np from torch.utils.data import TensorDataset, DataLoader from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.metrics import accuracy_score from bayes_opt import BayesianOptimization best_accuracy = 0.0 best_model = None device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print(f"设备: {device}") def get_data(): X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) scaler = StandardScaler() X_train = scaler.fit_transform(X_train) X_test = scaler.transform(X_test) X_train = torch.tensor(X_train, dtype=torch.float32).to(device) X_test = torch.tensor(X_test, dtype=torch.float32).to(device) y_train = torch.tensor(y_train, dtype=torch.long).to(device) y_test = torch.tensor(y_test, dtype=torch.long).to(device) return X_train, X_test, y_train, y_test class MLP(nn.Module): def __init__(self, input_dim, hidden1, hidden2, dropout_rate): super(MLP, self).__init__() self.model = nn.Sequential( nn.Linear(input_dim, hidden1), nn.ReLU(), nn.Dropout(dropout_rate), nn.Linear(hidden1, hidden2), nn.ReLU(), nn.Dropout(dropout_rate), nn.Linear(hidden2, 2) ) def forward(self, x): return self.model(x) def train_mlp(hidden1, hidden2, lr, dropout_rate, weight_decay, batch_size): global best_accuracy, best_model hidden1 = int(hidden1) hidden2 = int(hidden2) batch_size = int(batch_size) X_train, X_test, y_train, y_test = get_data() input_dim = X_train.shape[1] train_dataset = TensorDataset(X_train, y_train) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) model = MLP(input_dim, hidden1, hidden2, dropout_rate).to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=lr, weight_decay=weight_decay) model.train() epochs = 20 for epoch in range(epochs): for data, label in train_loader: optimizer.zero_grad() output = model(data) loss = criterion(output, label) loss.backward() optimizer.step() model.eval() with torch.no_grad(): y_pred = model(X_test).argmax(dim=1).cpu().numpy() y_true = y_test.cpu().numpy() acc = accuracy_score(y_true, y_pred) if acc > best_accuracy: best_accuracy = acc best_model = model print(f"\n发现更优模型!准确率: {acc:.4f}") return acc def bayesian_optimization(): pbounds = { 'hidden1': (32, 256), 'hidden2': (16, 128), 'lr': (1e-4, 1e-2), 'dropout_rate': (0.1, 0.5), 'weight_decay': (1e-5, 1e-3), 'batch_size': (32, 256), } optimizer = BayesianOptimization( f=train_mlp, pbounds=pbounds, random_state=42, verbose=2 ) optimizer.maximize(init_points=3, n_iter=10) print("\n" + "="*50) print("贝叶斯优化完成") print(f"最佳测试准确率: {optimizer.max['target']:.4f}") print(f"最佳超参数: {optimizer.max['params']}") print("="*50) return optimizer.max def save_best_model(): global best_model if best_model is not None: torch.save(best_model.state_dict(), "best_mlp_model.pth") print("\n最优模型已保存:best_mlp_model.pth") print(f"最优模型准确率: {best_accuracy:.4f}") else: print("未找到最优模型") if __name__ == "__main__": best_result = bayesian_optimization() save_best_model()3.运行效果
设备: cuda | iter | target | hidden1 | hidden2 | lr | dropou... | weight... | batch_... | ------------------------------------------------------------------------------------------------- 发现更优模型!准确率: 0.9785 | 1 | 0.9785 | 115.89698 | 122.48000 | 0.0073467 | 0.3394633 | 0.0001644 | 66.942772 | | 2 | 0.9725 | 45.010729 | 113.01172 | 0.0060510 | 0.3832290 | 3.037e-05 | 249.25980 | 发现更优模型!准确率: 0.9825 | 3 | 0.9825 | 218.46715 | 39.781980 | 0.0019000 | 0.1733618 | 0.0003111 | 149.54544 | | 4 | 0.981 | 227.22424 | 45.700258 | 0.0019841 | 0.4144344 | 0.0004332 | 137.46784 | | 5 | 0.979 | 224.08165 | 19.261477 | 0.0073002 | 0.2001550 | 0.0002476 | 206.83952 | 发现更优模型!准确率: 0.9870 | 6 | 0.987 | 170.35254 | 32.767894 | 0.0066508 | 0.2900235 | 0.0003652 | 143.34584 | | 7 | 0.98 | 169.70364 | 32.021540 | 0.0076808 | 0.3398859 | 0.0003341 | 143.18209 | | 8 | 0.968 | 166.19593 | 101.15967 | 0.0001455 | 0.3755693 | 7.709e-05 | 78.100896 | | 9 | 0.978 | 171.67927 | 30.865531 | 0.0056182 | 0.2547844 | 0.0009247 | 140.13546 | | 10 | 0.978 | 167.98075 | 38.545550 | 0.0076755 | 0.4065293 | 0.0007287 | 143.05541 | | 11 | 0.984 | 170.96096 | 32.689496 | 0.0049800 | 0.2569683 | 0.0002752 | 143.37508 | | 12 | 0.9845 | 217.57055 | 35.619517 | 0.0054640 | 0.2074799 | 0.0005053 | 150.93606 | 发现更优模型!准确率: 0.9920 | 13 | 0.992 | 216.52372 | 38.614819 | 0.0061758 | 0.2539666 | 0.0001237 | 154.98065 | ================================================================================================= ================================================== 贝叶斯优化完成 最佳测试准确率: 0.9920 最佳超参数: {'hidden1': np.float64(216.52372265940144), 'hidden2': np.float64(38.61481936855262), 'lr': np.float64(0.006175809340190158), 'dropout_rate': np.float64(0.2539666671286065), 'weight_decay': np.float64(0.00012376210103301903), 'batch_size': np.float64(154.98065397036225)} ================================================== 最优模型已保存:best_mlp_model.pth 最优模型准确率: 0.9920