在C#中实现深度学习通常需要依赖复杂的框架,但通过Keras.NET,我们可以在零外部依赖的情况下训练强大的深度学习模型。下面我将分享一个完整的实战案例,展示如何用C#和Keras.NET训练一个图像分类模型。
这个实现具有以下特点:
- 零外部依赖:仅使用Keras.NET和Numpy.NET库,无需安装Python或其他深度学习框架
- 完整的训练流程:包括模型构建、数据加载、训练、评估和保存
- 卷积神经网络:使用现代CNN架构进行图像分类
- 模型检查点:自动保存验证集表现最佳的模型
- 灵活的配置:可调整图像尺寸、批次大小和训练轮数
要运行此代码,你需要安装以下NuGet包:
- Keras.NET
- Numpy.NET
- SciSharp.TensorFlow.Redist
在实际应用中,你需要替换LoadData方法中的模拟数据加载逻辑,使用真实的图像数据。你可以使用如ImageSharp等库来处理图像加载和预处理。
通过这种方法,你可以在C#环境中完全实现深度学习模型的训练和部署,无需依赖Python环境,特别适合需要集成深度学习功能的.NET应用程序。
复制using Keras; using Keras.Layers; using Keras.Models; using Keras.Optimizers; using Numpy; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace DeepLearningExample { public class DeepLearningTrainer { private Sequential model; // 构建卷积神经网络模型 public void BuildModel(int imgWidth, int imgHeight, int numClasses) { // 创建序贯模型 model = new Sequential(); // 添加卷积层和池化层 model.Add(new Conv2D(32, new Shape(3, 3), activation: "relu", input_shape: new Shape(imgWidth, imgHeight, 3))); model.Add(new MaxPooling2D(pool_size: new Shape(2, 2))); model.Add(new Conv2D(64, new Shape(3, 3), activation: "relu")); model.Add(new MaxPooling2D(pool_size: new Shape(2, 2))); model.Add(new Conv2D(128, new Shape(3, 3), activation: "relu")); model.Add(new MaxPooling2D(pool_size: new Shape(2, 2))); // 展平并添加全连接层 model.Add(new Flatten()); model.Add(new Dense(128, activation: "relu")); model.Add(new Dropout(0.5)); model.Add(new Dense(numClasses, activation: "softmax")); // 编译模型 var opt = new Adam(lr: 0.001f); model.Compile(optimizer: opt, loss: "categorical_crossentropy", metrics: new string[] { "accuracy" }); Console.WriteLine("模型结构已构建:"); model.Summary(); } // 加载图像数据 public (NDarray xTrain, NDarray yTrain, NDarray xVal, NDarray yVal) LoadData(string dataPath, int imgWidth, int imgHeight) { Console.WriteLine($"开始加载数据: {dataPath}"); // 这里应该实现实际的图像加载和预处理逻辑 // 为简化示例,我们创建一些随机数据作为占位符 int trainSamples = 8000; int valSamples = 2000; // 创建随机训练数据 var xTrain = np.random.rand(trainSamples, imgWidth, imgHeight, 3); var yTrain = np.zeros((trainSamples, 10)); // 创建随机验证数据 var xVal = np.random.rand(valSamples, imgWidth, imgHeight, 3); var yVal = np.zeros((valSamples, 10)); // 为简化示例,随机分配类别 for (int i = 0; i < trainSamples; i++) { int label = new Random().Next(0, 10); yTrain[i, label] = 1; } for (int i = 0; i < valSamples; i++) { int label = new Random().Next(0, 10); yVal[i, label] = 1; } Console.WriteLine($"数据加载完成: 训练样本={trainSamples}, 验证样本={valSamples}"); return (xTrain, yTrain, xVal, yVal); } // 训练模型 public void TrainModel(NDarray xTrain, NDarray yTrain, NDarray xVal, NDarray yVal, int epochs = 10, int batchSize = 32) { Console.WriteLine($"开始训练模型: 轮数={epochs}, 批次大小={batchSize}"); // 设置回调函数 var callbacks = new List<BaseCallback> { new ModelCheckpoint("best_model.h5", monitor: "val_accuracy", save_best_only: true, verbose: 1), new EarlyStopping(monitor: "val_loss", patience: 3, verbose: 1), new TensorBoard(log_dir: "logs", histogram_freq: 1) }; // 训练模型 var history = model.Fit(xTrain, yTrain, batch_size: batchSize, epochs: epochs, validation_data: new NDarray[] { xVal, yVal }, callbacks: callbacks.ToArray(), verbose: 1); // 输出训练结果 Console.WriteLine("训练历史:"); foreach (var key in history.HistoryDict.Keys) { Console.WriteLine($"{key}: {string.Join(", ", history.HistoryDict[key].Select(v => v.ToString("0.0000")))}"); } } // 评估模型 public void EvaluateModel(NDarray xVal, NDarray yVal) { Console.WriteLine("开始评估模型..."); var scores = model.Evaluate(xVal, yVal, verbose: 1); Console.WriteLine($"验证集损失: {scores[0]:0.0000}"); Console.WriteLine($"验证集准确率: {scores[1] * 100:0.00}%"); } // 保存模型 public void SaveModel(string modelPath) { Console.WriteLine($"保存模型到: {modelPath}"); model.Save(modelPath); } } }