From 4da40089f5a6df213612ae8f13b58ed49d848ed8 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Fri, 14 Nov 2025 10:46:33 +0800 Subject: [PATCH] proj5 finished --- .../__pycache__/backend.cpython-313.pyc | Bin 0 -> 38445 bytes .../__pycache__/models.cpython-313.pyc | Bin 0 -> 19602 bytes proj5/machinelearning/models.py | 98 +++++++++++-- proj5/machinelearning/solution_steps.md | 138 ++++++++++++++++++ 4 files changed, 226 insertions(+), 10 deletions(-) create mode 100644 proj5/machinelearning/__pycache__/backend.cpython-313.pyc create mode 100644 proj5/machinelearning/__pycache__/models.cpython-313.pyc create mode 100644 proj5/machinelearning/solution_steps.md diff --git a/proj5/machinelearning/__pycache__/backend.cpython-313.pyc b/proj5/machinelearning/__pycache__/backend.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f83934c53a76f8e78cfa8997c531d116343ae4c GIT binary patch literal 38445 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 literal 0 HcmV?d00001 diff --git a/proj5/machinelearning/__pycache__/models.cpython-313.pyc b/proj5/machinelearning/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3cc595412b767e20005c4dd3f5017f511c8259de GIT binary patch literal 19602 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 0 else -1 @@ -80,7 +81,17 @@ class PerceptronModel(Module): """ with no_grad(): dataloader = DataLoader(dataset, batch_size=1, shuffle=True) - "*** YOUR CODE HERE ***" + while True: + converged = True + for batch in dataloader: + x = batch['x'] + y = batch['label'] + prediction = self.get_prediction(x) + if prediction != y.item(): + self.w.data += y.item() * x + converged = False + if converged: + break @@ -94,6 +105,9 @@ class RegressionModel(Module): # Initialize your model parameters here "*** YOUR CODE HERE ***" super().__init__() + self.layer1 = Linear(1, 256) + self.layer2 = Linear(256, 256) + self.layer3 = Linear(256, 1) @@ -107,6 +121,9 @@ class RegressionModel(Module): A node with shape (batch_size x 1) containing predicted y-values """ "*** YOUR CODE HERE ***" + x = relu(self.layer1(x)) + x = relu(self.layer2(x)) + return self.layer3(x) def get_loss(self, x, y): @@ -120,6 +137,7 @@ class RegressionModel(Module): Returns: a tensor of size 1 containing the loss """ "*** YOUR CODE HERE ***" + return mse_loss(self.forward(x), y) @@ -138,6 +156,27 @@ class RegressionModel(Module): """ "*** YOUR CODE HERE ***" + batch_size = 40 + dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True) + optimizer = optim.Adam(self.parameters(), lr=0.001) + scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=250, gamma=0.1) + + for epoch in range(1000): # Train for 1000 epochs, should be enough + total_loss = 0 + num_samples = 0 + for batch in dataloader: + optimizer.zero_grad() + loss = self.get_loss(batch['x'], batch['label']) + loss.backward() + optimizer.step() + total_loss += loss.item() * len(batch['x']) + num_samples += len(batch['x']) + + scheduler.step() + + avg_loss = total_loss / num_samples + if avg_loss < 0.02: + break @@ -167,6 +206,9 @@ class DigitClassificationModel(Module): input_size = 28 * 28 output_size = 10 "*** YOUR CODE HERE ***" + self.layer1 = Linear(input_size, 256) + self.layer2 = Linear(256, 128) + self.layer3 = Linear(128, output_size) @@ -186,6 +228,9 @@ class DigitClassificationModel(Module): (also called logits) """ """ YOUR CODE HERE """ + x = relu(self.layer1(x)) + x = relu(self.layer2(x)) + return self.layer3(x) @@ -203,6 +248,7 @@ class DigitClassificationModel(Module): Returns: a loss tensor """ """ YOUR CODE HERE """ + return cross_entropy(self.run(x), y) @@ -212,6 +258,16 @@ class DigitClassificationModel(Module): Trains the model. """ """ YOUR CODE HERE """ + batch_size = 100 + dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True) + optimizer = optim.Adam(self.parameters(), lr=0.001) + + for epoch in range(5): # Train for 5 epochs + for batch in dataloader: + optimizer.zero_grad() + loss = self.get_loss(batch['x'], batch['label']) + loss.backward() + optimizer.step() @@ -314,13 +370,18 @@ def Convolve(input: tensor, weight: tensor): This returns a subtensor who's first element is tensor[y,x] and has height 'height, and width 'width' """ - input_tensor_dimensions = input.shape - weight_dimensions = weight.shape - Output_Tensor = tensor(()) - "*** YOUR CODE HERE ***" - + input_h, input_w = input.shape + weight_h, weight_w = weight.shape + output_h = input_h - weight_h + 1 + output_w = input_w - weight_w + 1 - "*** End Code ***" + Output_Tensor = torch.zeros((output_h, output_w)) + + for y in range(output_h): + for x in range(output_w): + sub_tensor = input[y:y+weight_h, x:x+weight_w] + Output_Tensor[y, x] = tensordot(sub_tensor, weight, dims=2) + return Output_Tensor @@ -345,6 +406,10 @@ class DigitConvolutionalModel(Module): self.convolution_weights = Parameter(ones((3, 3))) """ YOUR CODE HERE """ + conv_output_size = 26 * 26 + hidden_size = 100 + self.layer1 = Linear(conv_output_size, hidden_size) + self.layer2 = Linear(hidden_size, output_size) @@ -361,6 +426,8 @@ class DigitConvolutionalModel(Module): x = stack(list(map(lambda sample: Convolve(sample, self.convolution_weights), x))) x = x.flatten(start_dim=1) """ YOUR CODE HERE """ + x = relu(self.layer1(x)) + return self.layer2(x) def get_loss(self, x, y): @@ -377,6 +444,7 @@ class DigitConvolutionalModel(Module): Returns: a loss tensor """ """ YOUR CODE HERE """ + return cross_entropy(self.forward(x), y) @@ -386,6 +454,16 @@ class DigitConvolutionalModel(Module): Trains the model. """ """ YOUR CODE HERE """ + batch_size = 64 + dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True) + optimizer = optim.Adam(self.parameters(), lr=0.001) + + for epoch in range(3): + for batch in dataloader: + optimizer.zero_grad() + loss = self.get_loss(batch['x'], batch['label']) + loss.backward() + optimizer.step() diff --git a/proj5/machinelearning/solution_steps.md b/proj5/machinelearning/solution_steps.md new file mode 100644 index 0000000..927e413 --- /dev/null +++ b/proj5/machinelearning/solution_steps.md @@ -0,0 +1,138 @@ +# **CS188 Proj5 机器学习实验完成步骤详解** + +本文档详细记录了在CS188项目5(机器学习)中,完成Q1、Q2、Q3和Q5四个部分的核心代码实现步骤。所有代码修改均在 `models.py` 文件中进行。 + +## **问题一 (Q1): 感知机 (Perceptron)** + +此部分的目标是实现一个二元分类感知机模型。 + +1. **`__init__(self, dimensions)` - 初始化** + * 初始化模型的权重 `self.w`。根据要求,权重需要是一个PyTorch的 `Parameter` 对象,以便自动评分系统能够识别。 + * 权重向量的维度被设置为 `(1, dimensions)`,并使用 `ones` 进行初始化。 + + ```python + from torch.nn import Parameter + from torch import ones + + self.w = Parameter(ones(1, dimensions)) + ``` + +2. **`run(self, x)` - 计算得分** + * 此函数计算感知机对输入数据 `x` 的得分。 + * 通过计算权重 `self.w` 和输入 `x` 的点积来实现。这里使用了 `tensordot` 函数。 + + ```python + from torch import tensordot + + return tensordot(self.w, x, dims=2) + ``` + +3. **`get_prediction(self, x)` - 获取预测** + * 根据 `run` 方法计算出的得分,判断数据点的类别。 + * 如果得分大于或等于0,则预测为类别 `1`;否则预测为 `-1`。 + + ```python + score = self.run(x) + return 1 if score.item() >= 0 else -1 + ``` + +4. **`train(self, dataset)` - 训练模型** + * 此函数的目标是训练感知机直到收敛(即在整个数据集上不再有分类错误)。 + * 使用一个 `while True` 循环,在每一轮迭代中遍历整个数据集。 + * 对于每一个数据点,获取模型的预测。如果预测错误,则根据感知机学习规则更新权重:`self.w.data += y.item() * x`,其中 `y` 是真实标签,`x` 是输入特征。 + * 设置一个标志位 `converged`。如果在一整轮的迭代中没有任何错误发生,则 `converged` 保持为 `True`,训练循环结束。 + +## **问题二 (Q2): 非线性回归 (Non-linear Regression)** + +此部分要求构建一个神经网络来近似 `sin(x)` 函数。 + +1. **`__init__(self)` - 初始化** + * 构建一个简单的两层全连接神经网络。 + * 第一层 (`self.layer1`) 是一个 `Linear` 层,将1维输入映射到100维的隐藏层。 + * 第二层 (`self.layer2`) 也是一个 `Linear` 层,将100维的隐藏层映射到1维的输出。 + + ```python + from torch.nn import Linear + + self.layer1 = Linear(1, 100) + self.layer2 = Linear(100, 1) + ``` + +2. **`forward(self, x)` - 前向传播** + * 定义数据在网络中的流动方式。 + * 输入 `x` 首先通过第一层,然后应用 `relu` 激活函数,最后通过第二层得到最终输出。 + + ```python + from torch.nn.functional import relu + + x = relu(self.layer1(x)) + return self.layer2(x) + ``` + +3. **`get_loss(self, x, y)` - 计算损失** + * 使用均方误差(Mean Squared Error)作为损失函数。 + * 调用 `forward(x)` 得到预测值,然后使用 `mse_loss` 计算与真实值 `y` 之间的损失。 + + ```python + from torch.nn.functional import mse_loss + + return mse_loss(self.forward(x), y) + ``` + +4. **`train(self, dataset)` - 训练模型** + * 使用 `Adam` 优化器进行梯度下降。 + * 设置合适的批处理大小(`batch_size`),例如50(因为Q2数据集大小为200,可以被50整除)。 + * 训练循环进行固定次数的迭代(Epoch),例如500次。在每个Epoch中,遍历数据加载器(`DataLoader`)中的所有批次,执行标准的训练步骤:梯度清零、计算损失、反向传播、更新权重。 + * 在每个Epoch结束后,计算整个数据集的平均损失。如果平均损失小于0.02,则提前终止训练。 + +## **问题三 (Q3): 数字分类 (Digit Classification)** + +此部分要求构建一个模型来对MNIST手写数字数据集进行分类。 + +1. **`__init__(self)` - 初始化** + * 构建一个具有两个隐藏层的多层感知机(MLP)。 + * 输入层大小为 `784` (28x28像素),输出层大小为 `10` (0-9共10个类别)。 + * 网络结构:`Linear(784, 256)` -> `Linear(256, 128)` -> `Linear(128, 10)`。 + +2. **`run(self, x)` - 前向传播** + * 数据流经两个隐藏层,每个隐藏层后都应用 `relu` 激活函数。 + * 输出层不使用激活函数,直接返回 logits 分数。 + +3. **`get_loss(self, x, y)` - 计算损失** + * 使用交叉熵损失函数 `cross_entropy`。 + * 一个关键点是,PyTorch的 `cross_entropy` 函数可以直接接受 one-hot 编码的浮点型标签 `y`。因此,直接将模型的输出 `self.run(x)` 和标签 `y` 传入即可。 + * (注:最初尝试使用 `y.argmax(dim=1)` 将 one-hot 标签转换为索引,但这会导致自动评分器中的梯度检查失败。直接传递 one-hot 标签解决了这个问题。) + +4. **`train(self, dataset)` - 训练模型** + * 同样使用 `Adam` 优化器和 `DataLoader`。批处理大小设置为100(可被训练集大小60000整除)。 + * 根据实验指导,训练5个Epoch就足以达到要求的准确率。 + * 因此,实现一个简单的循环,迭代5次,在其中执行标准的模型训练流程。 + * (注:最初尝试使用 `dataset.get_validation_accuracy(self)` 进行早停,但遇到了 `TypeError`。简化为固定Epoch次数的训练后,成功通过了测试。) + +## **问题五 (Q5): 卷积神经网络 (Convolutional Neural Networks)** + +此部分要求从零开始实现一个卷积函数,并构建一个简单的卷积神经网络。 + +1. **`Convolve(input: tensor, weight: tensor)` - 实现卷积函数** + * 此函数手动实现2D卷积操作,不使用PyTorch内置的卷积层。 + * 首先,根据输入张量和权重张量的尺寸,计算输出张量的尺寸(无填充,步长为1)。 + * 创建一个全为零的输出张量 `Output_Tensor`。 + * 使用嵌套循环遍历输出张量的每一个位置 `(y, x)`。 + * 在每个位置,从输入张量中提取一个与权重张量大小相同的子张量 `sub_tensor`。 + * 使用 `tensordot` 计算 `sub_tensor` 和 `weight` 的点积(即元素乘积之和),并将结果存入 `Output_Tensor[y, x]`。 + * 返回计算完成的 `Output_Tensor`。 + +2. **`DigitConvolutionalModel` - 构建CNN模型** + * **`__init__(self)`**: + * 模型包含一个 `3x3` 的卷积核 `self.convolution_weights`。 + * 卷积操作的输出是一个 `26x26` 的特征图,展平后大小为 `676`。 + * 在卷积层之后,添加一个简单的全连接网络,例如 `Linear(676, 100)` -> `ReLU` -> `Linear(100, 10)`。 + * **`forward(self, x)`**: + * 函数的前半部分已提供,它会将输入的 `(batch_size, 784)` 数据重塑为 `(batch_size, 28, 28)` 的图像,然后使用我们实现的 `Convolve` 函数对批次中的每个样本进行卷积,最后将结果展平。 + * 我们需要做的,是将这个展平后的一维向量传入我们定义的两层全连接网络中,并返回最终的分类分数。 + * **`get_loss(self, x, y)` 和 `train(self, dataset)`**: + * 这两个函数的实现与Q3中的 `DigitClassificationModel` 非常相似。 + * `get_loss` 使用 `cross_entropy`。 + * `train` 使用 `Adam` 优化器,训练一个较少的Epoch次数(例如3次),因为此问题的数据集较为简单,训练速度很快。 + +---