Why does the hash value of models change everytime I save it?

I am using torch.save() to save a model file. However, everytime I save it, it changes. Why so?

netG_1 = torch.load('netG.pth')
netG_2 = torch.load('netG.pth')

torch.save(netG_1, 'netG_1.pth')
torch.save(netG_2, 'netG_2.pth')

Using md5sum *.pth:

779f0fefca47d17a0644033f9b65e594  netG_1.pth
476f502ec2d1186c349cdeba14983d09  netG_2.pth
b0ceec8ac886a11b79f73fc04f51c6f9  netG.pth
1 Like

You would need to look deeper in the serialization mechanism for tensors but it is possible that it uses their address in memory as an “id” to make sure to save each tensor only once. In that case, every time you load the model, it gets to a new place in memory and so "id"s will change.

The model is an instance of this class:

As the model refers to a lot of stuff, I printed the final one here, using print(netG)

G_NET(
  (ca_net): CA_NET(
    (fc): Linear(in_features=256, out_features=400, bias=True)
    (relu): GLU()
  )
  (h_net1): INIT_STAGE_G(
    (fc): Sequential(
      (0): Linear(in_features=200, out_features=16384, bias=False)
      (1): BatchNorm1d(16384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (2): GLU()
    )
    (upsample1): Sequential(
      (0): Upsample(scale_factor=2, mode=nearest)
      (1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (3): GLU()
    )
    (upsample2): Sequential(
      (0): Upsample(scale_factor=2, mode=nearest)
      (1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (3): GLU()
    )
    (upsample3): Sequential(
      (0): Upsample(scale_factor=2, mode=nearest)
      (1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (3): GLU()
    )
    (upsample4): Sequential(
      (0): Upsample(scale_factor=2, mode=nearest)
      (1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (3): GLU()
    )
  )
  (img_net1): GET_IMAGE_G(
    (img): Sequential(
      (0): Conv2d(32, 3, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (1): Tanh()
    )
  )
  (h_net2): NEXT_STAGE_G(
    (att): GlobalAttentionGeneral(
      (conv_context): Conv2d(256, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (sm): Softmax()
    )
    (residual): Sequential(
      (0): ResBlock(
        (block): Sequential(
          (0): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): GLU()
          (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (1): ResBlock(
        (block): Sequential(
          (0): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): GLU()
          (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
    )
    (upsample): Sequential(
      (0): Upsample(scale_factor=2, mode=nearest)
      (1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (3): GLU()
    )
  )
  (img_net2): GET_IMAGE_G(
    (img): Sequential(
      (0): Conv2d(32, 3, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (1): Tanh()
    )
  )
  (h_net3): NEXT_STAGE_G(
    (att): GlobalAttentionGeneral(
      (conv_context): Conv2d(256, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (sm): Softmax()
    )
    (residual): Sequential(
      (0): ResBlock(
        (block): Sequential(
          (0): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): GLU()
          (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (1): ResBlock(
        (block): Sequential(
          (0): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): GLU()
          (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
          (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
    )
    (upsample): Sequential(
      (0): Upsample(scale_factor=2, mode=nearest)
      (1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (3): GLU()
    )
  )
  (img_net3): GET_IMAGE_G(
    (img): Sequential(
      (0): Conv2d(32, 3, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (1): Tanh()
    )
  )
)