关于ConvLSTM的小实验

实验要求:

1.HKO-07 先居中 取 360*360 然后缩放到128*128(532→222)

2.训练模型 batch=4 迭代10万次, 每2000次验证一次,

以最低B-MSE保存训练模型,最后一次的训练模型也同时保存

3.随机数种子 设置为 12345098

要求一的实现:①在数据加载这里对数据进行处理(valid_batch同理)

原代码:
train_batch = torch.from_numpy(train_batch.astype(np.float32)).to(cfg.GLOBAL.DEVICE) / 255.0
train_data = train_batch[:IN_LEN, ...]
train_label = train_batch[IN_LEN:IN_LEN + OUT_LEN, ...]
修改后的代码:
import torchvision.transforms as transforms
import torch.nn.functional as F
train_batch = torch.from_numpy(train_batch.astype(np.float32)).to(cfg.GLOBAL.DEVICE) / 255.0
# 裁剪+缩放
b, s, c, h, w = train_batch.shape
# 变形为 (b * s, c, h, w) 以适应批处理
train_batch = train_batch.view(-1, c, h, w)
# 定义转换操作:先居中裁剪,然后缩放到128x128
transform = transforms.Compose([
    transforms.CenterCrop(384),
    transforms.Resize(128)
])
# 处理所有图像,使用批处理
output_data = transform(train_batch)
# 还原到原来的批次和序列形状
train_batch = output_data.view(b, s, c, 128, 128)

train_data = train_batch[:IN_LEN, ...]
train_label = train_batch[IN_LEN:IN_LEN + OUT_LEN, ...]

②修改网络模型参数

encoder = Encoder(convlstm_encoder_params[0], convlstm_encoder_params[1]).to(cfg.GLOBAL.DEVICE)
forecaster = Forecaster(convlstm_forecaster_params[0], convlstm_forecaster_params[1]).to(cfg.GLOBAL.DEVICE)

这两句里面的参数需要修改

具体是在net_params.py文件里面

# build model
convlstm_encoder_params = [
    [
        OrderedDict({'conv1_leaky_1': [1, 8, 7, 5, 1]}),
        OrderedDict({'conv2_leaky_1': [64, 192, 5, 3, 1]}),
        OrderedDict({'conv3_leaky_1': [192, 192, 3, 2, 1]}),
    ],

    [
        ConvLSTM(input_channel=8, num_filter=64, b_h_w=(batch_size, 96, 96),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 32, 32),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 16, 16),
                 kernel_size=3, stride=1, padding=1),
    ]
]

convlstm_forecaster_params = [
    [
        OrderedDict({'deconv1_leaky_1': [192, 192, 4, 2, 1]}),
        OrderedDict({'deconv2_leaky_1': [192, 64, 5, 3, 1]}),
        OrderedDict({
            'deconv3_leaky_1': [64, 8, 7, 5, 1],
            'conv3_leaky_2': [8, 8, 3, 1, 1],
            'conv3_3': [8, 1, 1, 1, 0]
        }),
    ],

    [
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 16, 16),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 32, 32),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=64, num_filter=64, b_h_w=(batch_size, 96, 96),
                 kernel_size=3, stride=1, padding=1),
    ]
]

其中,'conv1_leaky_1': [1, 8, 7, 5, 1]、'deconv1_leaky_1': [192, 192, 4, 2, 1]的参数依次表示

  1. 输入通道数(input_channels):输入到该层的特征图的通道数。
  2. 输出通道数(output_channels):该层卷积核的数量,也就是输出特征图的通道数。
  3. 卷积核大小(kernel_size):卷积核的高度和宽度。
  4. 步长(stride):卷积核在输入特征图上移动的步长。
  5. 填充(padding):在输入特征图的边界上添加零值的大小,以控制输出特征图的大小。

因为原来采样是480→96→32→16,现在是128→64→32→16

所以stride从5、3、2改成2、2、2
kernel_size在卷积层里按公式“output_size=(input_size−kernel_size+2×padding)/stride+1”来推算
在反卷积层里按公式“output_height=(input_height−1)×stride−2×padding+kernel_size”来推算

修改后的代码:

# build model
convlstm_encoder_params_222 = [
    [
        OrderedDict({'conv1_leaky_1': [1, 8, 4, 2, 1]}),
        OrderedDict({'conv2_leaky_1': [64, 192, 4, 2, 1]}),
        OrderedDict({'conv3_leaky_1': [192, 192, 4, 2, 1]}),
    ],

    [
        ConvLSTM(input_channel=8, num_filter=64, b_h_w=(batch_size, 64, 64),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 32, 32),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 16, 16),
                 kernel_size=3, stride=1, padding=1),
    ]
]

convlstm_forecaster_params_222 = [
    [
        OrderedDict({'deconv1_leaky_1': [192, 192, 4, 2, 1]}),
        OrderedDict({'deconv2_leaky_1': [192, 64, 4, 2, 1]}),
        OrderedDict({
            'deconv3_leaky_1': [64, 8, 4, 2, 1],
            'conv3_leaky_2': [8, 8, 3, 1, 1],
            'conv3_3': [8, 1, 1, 1, 0]
        }),
    ],

    [
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 16, 16),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=192, num_filter=192, b_h_w=(batch_size, 32, 32),
                 kernel_size=3, stride=1, padding=1),
        ConvLSTM(input_channel=64, num_filter=64, b_h_w=(batch_size, 64, 64),
                 kernel_size=3, stride=1, padding=1),
    ]
]

要求二的实现:修改模型保存逻辑

原代码的模型保存:(和模型测试是相互独立的)
if itera % test_and_save_checkpoint_iterations == 0:
    modelsave_path = osp.join(model_save_dir, 'encoder_forecaster_{}.pth'.format(itera))
    print(f'modelsave_path={modelsave_path}')
    torch.save(encoder_forecaster.state_dict(), modelsave_path)
修改后的代码:
# 在没有梯度的情况下进行验证
with torch.no_grad():……
之后添加模型保存代码
#设置best_valid_mse的值为无限大,方便后续比较大小保存模型
best_valid_mse = float('inf')
mean_valid_mse = np.mean(valid_mse)#valid_mse是个数组,所以要取平均值
if mean_valid_mse < best_valid_mse:
    best_valid_mse = mean_valid_mse
    print(f'itera={itera}')
    print(f'best_valid_mse={best_valid_mse}')
    modelsave_path = osp.join(model_save_dir, 'encoder_forecaster_{}.pth'.format(itera))
    print(f'modelsave_path={modelsave_path}')
    torch.save(encoder_forecaster.state_dict(), modelsave_path)

要求三的实现:
添加一段代码:

def set_seed(seed=12345098):
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed(seed)
        torch.cuda.manual_seed_all(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

在main函数里,初始化阶段调用

#设置随机数种子
set_seed()

与随机数种子相关的设置

  1. random.seed(seed):设置 Python 内置随机数生成器的种子。
  2. np.random.seed(seed):设置 NumPy 随机数生成器的种子。
  3. torch.manual_seed(seed):设置 PyTorch 随机数生成器的种子。
  4. torch.cuda.manual_seed(seed):设置当前 CUDA 设备的随机数种子。
  5. torch.cuda.manual_seed_all(seed):设置所有 CUDA 设备的随机数种子。
  6. torch.backends.cudnn.deterministic = True:使 PyTorch 使用确定性算法,以确保每次运行时得到相同的结果。
  7. torch.backends.cudnn.benchmark = False:禁用 PyTorch 的自动优化,以确保结果的一致性。

在设置随机数种子时,可以根据具体的应用场景和需求选择需要使用的语句。通常情况下,使用前述的这些语句可以确保实验结果的可重复性和稳定性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值