# 入门 ## 安装 推荐使用 uv 安装。 ```bash uv add git+https://github.com/wliafe/mltools.git ``` 或者使用 pip 安装。 ```bash pip install git+https://github.com/wliafe/mltools.git ``` ## 编写一个项目 项目名称为 mlp,项目内容为利用 mlp 对 mnist 数据集进行分类。 ### 项目结构 ```text project ├── data │ ├── MNIST │ └── .gitignore ├── results │ ├── - │ │ ├── .json │ │ ├── .log │ │ ├── .png │ │ └── .pt │ └── .gitignore ├── src │ ├── dataloader.py │ └── .ipynb ├── .gitignore └── README.md ``` 其中,`src` 目录下存放的是 mlp 的代码,`results` 目录下存放的是 mlp 的结果,`data` 目录下存放的是 mnist 数据集。 ### 数据集获取 ```python def mnist(path='../data', batch_size=100): download = False if Path(f'{path}/MNIST').exists() else True trans = transforms.ToTensor() # 数据集格式转换 train_data = datasets.MNIST(root=path, train=True, transform=trans, download=download) test_data = datasets.MNIST(root=path, train=False, transform=trans, download=download) train_data, val_data = mltools.split_data(train_data, [9, 1]) # 训练集和验证集比例9:1 return mltools.iter_data([train_data, val_data, test_data], batch_size) # 返回数据迭代器 ``` 使用 [split_data()](mltools.data.split_data) 按比例划分数据集。 使用 [iter_data()](mltools.data.iter_data) 构建 DataLoader 类。 ### 参数设置 ```python device = torch.device("cuda") train_iter, val_iter, test_iter = dl.mnist(batch_size=1000) # 获取训练集、验证集、测试集 model = nn.Sequential(nn.Flatten(), nn.Linear(784, 256), nn.ReLU(), nn.Linear(256, 10)) # 设置模型结构 model.to(device) loss = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=1e-1) ml = mltools.MachineLearning("mlp") ml.add_model(model) epoch, timer, recorder = ml.batch_create() ``` 每次初始化 [MachineLearning](mltools.learn.MachineLearning) 类时都将生成 `results/-` 文件夹,文件夹的命名格式为 `时间-文件名`,其中时间格式为 `年-月-日-时-分-秒`,文件夹中包含的文件如下: + `文件名.json`:训练结果 + `文件名.log`:训练日志 + `文件名.png`:训练曲线 + `文件名.pt`:模型参数 > v1.0.11 新增创建 data 目录,并在 results 和 data 目录中自动创建 `.gitignore` 文件,以在 git 版本控制中忽略整个文件夹。 > v1.0.11 模型参数文件后缀为 `.pth`。 使用 [add_model()](mltools.learn.MachineLearning.add_model) 将模型纳入管理。 使用 [batch_create()](mltools.learn.MachineLearning.batch_create) 创建 [Epoch](mltools.learn.Epoch)、[Timer](mltools.utils.Timer)、[Recorder](mltools.utils.Recorder) 实例。 使用 [create_epoch()](mltools.learn.MachineLearning.create_epoch)、[create_timer()](mltools.learn.MachineLearning.create_timer)、[create_recorder()](mltools.learn.MachineLearning.create_recorder) 分别创建 [Epoch](mltools.learn.Epoch)、[Timer](mltools.utils.Timer)、[Recorder](mltools.utils.Recorder) 实例。 ### 训练模型 ```python # 训练模型 num_epochs = epoch(20) animator = ml.create_animator( xlabel="epoch", xlim=[0, epoch.totol_epoch + 1], ylim=-0.1, legend=["train loss", "train acc", "val acc"] ) # 创建动画器 for current_epoch in range(1, num_epochs + 1): timer.start() # 开始计时 # 计算训练集 metric_train = mltools.Accumulator(3) # 累加器:(train_loss, train_acc, train_size) model.train() # 训练模式 for x, y in train_iter: x, y = x.to(device), y.to(device) # 转换x、y y_train = model(x) # 计算模型 train_loss = loss(y_train, y) # 计算损失 train_pred = y_train.argmax(dim=1) # 计算预测值 train_acc = (train_pred == y).sum() # 计算准确数 # 梯度更新 optimizer.zero_grad() train_loss.backward() optimizer.step() metric_train.add(train_loss * y.numel(), train_acc, y.numel()) # 累加损失、准确数、样本数 recorder[0].append(metric_train[0] / metric_train[2]) # 计算平均损失 recorder[1].append(metric_train[1] / metric_train[2]) # 计算准确率 # 计算验证集 metric_val = mltools.Accumulator(2) # 累加器:(val_loss, val_size) model.eval() # 验证模式 with torch.no_grad(): for x, y in val_iter: x, y = x.to(device), y.to(device) # 转换x、y y_val = model(x) # 计算模型 val_pred = y_val.argmax(dim=1) # 计算预测值 val_acc = (val_pred == y).sum() # 计算准确数 metric_val.add(val_acc, y.numel()) # 累加准确数、样本数 recorder[2].append(metric_val[0] / metric_val[1]) # 计算准确率 timer.stop() # 停止计时 # 打印输出值 ml.logger.info(f"train loss {recorder[0][-1]:.3f}, train acc {recorder[1][-1]:.3f}, val acc {recorder[2][-1]:.3f}") ml.print_training_time_massage(timer, num_epochs, current_epoch) ml.logger.info(f"trained on {str(device)}") animator.show(recorder.data) else: # 打印输出值 ml.logger.info(f"train loss {recorder[0][-1]:.3f}, train acc {recorder[1][-1]:.3f}, val acc {recorder[2][-1]:.3f}") ml.print_training_time_massage(timer, num_epochs, current_epoch) ml.logger.info(f"trained on {str(device)}") animator.show(recorder.data) ml.save() ``` [Epoch](mltools.learn.Epoch) 是循环器,用于循环训练模型。其中参数 num_epochs 为训练迭代总次数,并不是训练次数,因此当你已经迭代20次想再迭代20次时, num_epochs 应该为40。 使用 [create_animator()](mltools.learn.MachineLearning.create_animator) 创建 [Animator](mltools.draw.Animator) 实例。 [Animator](mltools.draw.Animator) 是动画器,用于绘制训练过程中的变化趋势。 [Accumulator](mltools.utils.Accumulator) 是累加器,这里初始化参数为3,因此创建的是三元累加器。 [Recorder](mltools.utils.Recorder) 是记录器,记录每一次循环的数据,例如:训练损失、训练集准确率、验证集准确率等。Recorder 记录的数据可以作为动画器画图的数据来源。 [Timer](mltools.utils.Timer) 是计时器,用于记录训练时间。 所有的打印输出一律使用 logger 打印,方便记入日志。 [print_training_time_massage()](mltools.learn.MachineLearning.print_training_time_massage) 是打印训练时间的函数,用于打印已训练时长、平均训练时长、预估剩余训练时长。 [save()](mltools.learn.MachineLearning.save) 用于保存所有 MachineLearning 创建和添加的工具的信息,具体的说就是 epoch、timer、recorder、model、animator 等信息。 使用 [load()](mltools.learn.MachineLearning.load) 加载之前保存的 MachineLearning 实例,可以在上次训练的基础上继续训练。 ### 测试模型 ```python model.eval() metric = mltools.Accumulator(2) # 累加器:(test_acc, test_size) with torch.no_grad(): for x, y in test_iter: x, y = x.to(device), y.to(device) # 转换x、y y_test = model(x) # 计算模型 test_pred = y_test.argmax(dim=1) # 计算预测值 test_acc = (test_pred == y).sum() # 计算准确数 metric.add(test_acc, y.numel()) # 累加准确数、样本数 ml.logger.info(f"test acc {metric[0] / metric[1]:.3f}") # 计算准确率并输出 ``` ### 预测模型 ```python model.eval() x, y = next(iter(test_iter)) # 从测试中取一个批量 x, y = x[:10].to(device), y[:10].to(device) # 转换x、y y_pred = model(x) # 计算模型 y_pred = y_pred.argmax(dim=1) # 计算预测值 labels = [f"real:{y[index]}\npred:{y_pred[index]}" for index in range(y.numel())] mltools.images(x.squeeze(1), labels, shape=(2, 5)) ``` [images()](mltools.draw.images) 用于绘制图片。