将权重从Keras分配给Torch模型。

huangapple go评论92阅读模式
英文:

Assign weights from keras to torch model

问题

我正在制作一个用于检查动画脸部是否相似的项目。我尝试自己训练一个模型,但进展不明显。因此,我决定使用已经训练好的模型并调整它以满足我的需求。我在GitHub上找到了这个模型

模型结构如下:

  1. N_CATEGORIES = 203
  2. IMAGE_SIZE = 224
  3. input_tensor = Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3))
  4. base_model = VGG16(weights='imagenet', include_top=False,input_tensor=input_tensor)
  5. x = base_model.output
  6. x = GlobalAveragePooling2D()(x)
  7. x = Dense(1024, activation='relu')(x)
  8. predictions = Dense(N_CATEGORIES, activation='softmax')(x)
  9. model = Model(inputs=base_model.input, outputs=predictions)
  10. for layer in base_model.layers[:15]:
  11. layer.trainable = False

Keras模型概要如下:

  1. Model: "model_1"
  2. Layer (type) Output Shape Param
  3. input_1 (InputLayer) [(None, 224, 224, 3)] 0
  4. block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
  5. block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
  6. block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
  7. block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
  8. block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
  9. block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
  10. block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
  11. block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
  12. block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
  13. block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
  14. block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
  15. block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
  16. block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
  17. block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
  18. block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
  19. block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
  20. block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
  21. block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
  22. global_average_pooling2d_1 (None, 512) 0
  23. (GlobalAveragePooling2D)
  24. dense_1 (Dense) (None, 1024) 525312
  25. dense_2 (Dense) (None, 203) 208075
  26. =================================================================

我下载了这个模型的.hdf5文件,但我无法将其转换为.pt格式。我在PyTorch中创建了类似于VGG16的结构:

  1. import torch
  2. import torch.nn as nn
  3. class CustomModel(nn.Module):
  4. def __init__(self):
  5. super(CustomModel, self).__init__()
  6. self.block1 = nn.Sequential(
  7. nn.Conv2d(3, 64, kernel_size=3, padding=1),
  8. nn.ReLU(),
  9. nn.Conv2d(64, 64, kernel_size=3, padding=1),
  10. nn.ReLU(),
  11. nn.MaxPool2d(kernel_size=2, stride=2)
  12. )
  13. # 你可以继续添加其他块...
  14. self.fc1 = nn.Linear(512, 1024)
  15. self.fc2 = nn.Linear(1024, 203)
  16. def forward(self, x):
  17. x = self.block1(x)
  18. # 你可以继续添加其他块...
  19. x = self.fc1(x)
  20. x = self.fc2(x)
  21. return x
  22. pytorch_model = CustomModel()

然后,你可以将Keras模型的权重加载到PyTorch模型中,但需要进行一些额外的处理,因为它们的结构不同。你可以参考此代码示例中的方法。你需要逐层复制权重。

请注意,这可能需要一些手动操作,因为Keras和PyTorch的模型结构不完全相同。你需要确保权重的顺序和形状正确匹配。希望这可以帮助你进行权重转换。

英文:

I am making a project for checking if anime faces is similar or not. I tried training a model by myself, but it doesn't make significant progress. So I decided to take already trained model and tune it to my needs. I found this model on github.

The model structure is:

  1. N_CATEGORIES = 203
  2. IMAGE_SIZE = 224
  3. input_tensor = Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3))
  4. base_model = VGG16(weights='imagenet', include_top=False,input_tensor=input_tensor)
  5. x = base_model.output
  6. x = GlobalAveragePooling2D()(x)
  7. x = Dense(1024, activation='relu')(x)
  8. predictions = Dense(N_CATEGORIES, activation='softmax')(x)
  9. model = Model(inputs=base_model.input, outputs=predictions)
  10. for layer in base_model.layers[:15]:
  11. layer.trainable = False

Keras model summary:

  1. Model: "model_1"
  2. Layer (type) Output Shape Param
  3. input_1 (InputLayer) [(None, 224, 224, 3)] 0
  4. block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
  5. block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
  6. block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
  7. block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
  8. block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
  9. block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
  10. block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
  11. block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
  12. block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
  13. block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
  14. block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
  15. block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
  16. block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
  17. block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
  18. block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
  19. block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
  20. block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
  21. block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
  22. global_average_pooling2d_1 (None, 512) 0
  23. (GlobalAveragePooling2D)
  24. dense_1 (Dense) (None, 1024) 525312
  25. dense_2 (Dense) (None, 203) 208075
  26. =================================================================

I downloaded an .hdf5 file for this model. By I can't convert it to .pt format. I made similar to vgg16 structure in torch:

  1. import torch
  2. import torch.nn as nn
  3. class CustomModel(nn.Module):
  4. def __init__(self):
  5. super(CustomModel, self).__init__()
  6. self.block1 = nn.Sequential(
  7. nn.Conv2d(3, 64, kernel_size=3, padding=1),
  8. nn.ReLU(),
  9. nn.Conv2d(64, 64, kernel_size=3, padding=1),
  10. nn.ReLU(),
  11. nn.MaxPool2d(kernel_size=2, stride=2)
  12. )
  13. self.block2 = nn.Sequential(
  14. nn.Conv2d(64, 128, kernel_size=3, padding=1),
  15. nn.ReLU(),
  16. nn.Conv2d(128, 128, kernel_size=3, padding=1),
  17. nn.ReLU(),
  18. nn.MaxPool2d(kernel_size=2, stride=2)
  19. )
  20. self.block3 = nn.Sequential(
  21. nn.Conv2d(128, 256, kernel_size=3, padding=1),
  22. nn.ReLU(),
  23. nn.Conv2d(256, 256, kernel_size=3, padding=1),
  24. nn.ReLU(),
  25. nn.Conv2d(256, 256, kernel_size=3, padding=1),
  26. nn.ReLU(),
  27. nn.MaxPool2d(kernel_size=2, stride=2)
  28. )
  29. self.block4 = nn.Sequential(
  30. nn.Conv2d(256, 512, kernel_size=3, padding=1),
  31. nn.ReLU(),
  32. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  33. nn.ReLU(),
  34. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  35. nn.ReLU(),
  36. nn.MaxPool2d(kernel_size=2, stride=2)
  37. )
  38. self.block5 = nn.Sequential(
  39. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  40. nn.ReLU(),
  41. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  42. nn.ReLU(),
  43. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  44. nn.ReLU(),
  45. nn.MaxPool2d(kernel_size=2, stride=2)
  46. )
  47. self.global_avg_pool = nn.AdaptiveAvgPool2d((1, 1))
  48. self.fc1 = nn.Linear(512, 1024)
  49. self.fc2 = nn.Linear(1024, 203)
  50. def forward(self, x):
  51. x = self.block1(x)
  52. x = self.block2(x)
  53. x = self.block3(x)
  54. x = self.block4(x)
  55. x = self.block5(x)
  56. x = self.global_avg_pool(x)
  57. x = torch.flatten(x, 1)
  58. x = self.fc1(x)
  59. x = self.fc2(x)
  60. return x
  61. pytorch_model = CustomModel()

I imported weight to keras:

  1. from keras.models import load_model
  2. model = load_model('animeface_vgg16.hdf5')
  3. weights=model.get_weights()

Tried to follow method like in this code example. I understand how to assing keras weights to fc layers. But there wasn't any example with convolutional layers.

I found only examples of building model structure in other questions on stack overflow, but nobody showed how to assign weights to it.

Please explain me how to do it.

答案1

得分: 0

  1. 找到了答案以下是模型结构
  2. ```python
  3. import torch
  4. import torch.nn as nn
  5. class CustomModel(nn.Module):
  6. def __init__(self, n_categories):
  7. super(CustomModel, self).__init__()
  8. self.block1 = nn.Sequential(
  9. nn.Conv2d(3, 64, kernel_size=3, padding=1),
  10. nn.ReLU(),
  11. nn.Conv2d(64, 64, kernel_size=3, padding=1),
  12. nn.ReLU(),
  13. nn.MaxPool2d(kernel_size=2, stride=2)
  14. )
  15. self.block2 = nn.Sequential(
  16. nn.Conv2d(64, 128, kernel_size=3, padding=1),
  17. nn.ReLU(),
  18. nn.Conv2d(128, 128, kernel_size=3, padding=1),
  19. nn.ReLU(),
  20. nn.MaxPool2d(kernel_size=2, stride=2)
  21. )
  22. self.block3 = nn.Sequential(
  23. nn.Conv2d(128, 256, kernel_size=3, padding=1),
  24. nn.ReLU(),
  25. nn.Conv2d(256, 256, kernel_size=3, padding=1),
  26. nn.ReLU(),
  27. nn.Conv2d(256, 256, kernel_size=3, padding=1),
  28. nn.ReLU(),
  29. nn.MaxPool2d(kernel_size=2, stride=2)
  30. )
  31. self.block4 = nn.Sequential(
  32. nn.Conv2d(256, 512, kernel_size=3, padding=1),
  33. nn.ReLU(),
  34. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  35. nn.ReLU(),
  36. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  37. nn.ReLU(),
  38. nn.MaxPool2d(kernel_size=2, stride=2)
  39. )
  40. self.block5 = nn.Sequential(
  41. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  42. nn.ReLU(),
  43. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  44. nn.ReLU(),
  45. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  46. nn.ReLU(),
  47. nn.MaxPool2d(kernel_size=2, stride=2),
  48. nn.AdaptiveAvgPool2d((1, 1))
  49. )
  50. self.dense = nn.Sequential(
  51. nn.Linear(512, 1024),
  52. nn.ReLU(),
  53. nn.Linear(1024, n_categories),
  54. nn.Softmax(dim=0)
  55. )
  56. def forward(self, x):
  57. x = self.block1(x)
  58. x = self.block2(x)
  59. x = self.block3(x)
  60. x = self.block4(x)
  61. x = self.block5(x)
  62. x = torch.flatten(x)
  63. x = self.dense(x)
  64. return x
  65. N_CATEGORIES = 203
  66. pytorch_model = CustomModel(N_CATEGORIES)

加载权重:

  1. pytorch_model.block1[0].weight.data = torch.from_numpy(np.transpose(weights[0]))
  2. pytorch_model.block1[0].bias.data = torch.from_numpy(weights[1])
  3. pytorch_model.block1[2].weight.data = torch.from_numpy(np.transpose(weights[2]))
  4. pytorch_model.block1[2].bias.data = torch.from_numpy(weights[3])
  5. pytorch_model.block2[0].weight.data = torch.from_numpy(np.transpose(weights[4]))
  6. pytorch_model.block2[0].bias.data = torch.from_numpy(weights[5])
  7. pytorch_model.block2[2].weight.data = torch.from_numpy(np.transpose(weights[6]))
  8. pytorch_model.block2[2].bias.data = torch.from_numpy(weights[7])
  9. pytorch_model.block3[0].weight.data = torch.from_numpy(np.transpose(weights[8]))
  10. pytorch_model.block3[0].bias.data = torch.from_numpy(weights[9])
  11. pytorch_model.block3[2].weight.data = torch.from_numpy(np.transpose(weights[10]))
  12. pytorch_model.block3[2].bias.data = torch.from_numpy(weights[11])
  13. pytorch_model.block3[4].weight.data = torch.from_numpy(np.transpose(weights[12]))
  14. pytorch_model.block3[4].bias.data = torch.from_numpy(weights[13])
  15. pytorch_model.block4[0].weight.data = torch.from_numpy(np.transpose(weights[14]))
  16. pytorch_model.block4[0].bias.data = torch.from_numpy(weights[15])
  17. pytorch_model.block4[2].weight.data = torch.from_numpy(np.transpose(weights[16]))
  18. pytorch_model.block4[2].bias.data = torch.from_numpy(weights[17])
  19. pytorch_model.block4[4].weight.data = torch.from_numpy(np.transpose(weights[18]))
  20. pytorch_model.block4[4].bias.data = torch.from_numpy(weights[19])
  21. pytorch_model.block5[0].weight.data = torch.from_numpy(np.transpose(weights[20]))
  22. pytorch_model.block5[0].bias.data = torch.from_numpy(weights[21])
  23. pytorch_model.block5[2].weight.data = torch.from_numpy(np.transpose(weights[22]))
  24. pytorch_model.block5[2].bias.data = torch.from_numpy(weights[23])
  25. pytorch_model.block5[4].weight.data = torch.from_numpy(np.transpose(weights[24]))
  26. pytorch_model.block5[4].bias.data = torch.from_numpy(weights[25])
  27. pytorch_model.dense[0].weight.data = torch.from_numpy(np.transpose(weights[26]))
  28. pytorch_model.dense[0].bias.data = torch.from_numpy(weights[27])
  29. pytorch_model.dense[2].weight.data = torch.from_numpy(np.transpose(weights[28]))
  30. pytorch_model.dense[2].bias.data = torch.from_numpy(weights[29])
英文:

Found an answer by myself. Here is a model structure:

  1. import torch
  2. import torch.nn as nn
  3. class CustomModel(nn.Module):
  4. def __init__(self, n_categories):
  5. super(CustomModel, self).__init__()
  6. self.block1 = nn.Sequential(
  7. nn.Conv2d(3, 64, kernel_size=3, padding=1),
  8. nn.ReLU(),
  9. nn.Conv2d(64, 64, kernel_size=3, padding=1),
  10. nn.ReLU(),
  11. nn.MaxPool2d(kernel_size=2, stride=2)
  12. )
  13. self.block2 = nn.Sequential(
  14. nn.Conv2d(64, 128, kernel_size=3, padding=1),
  15. nn.ReLU(),
  16. nn.Conv2d(128, 128, kernel_size=3, padding=1),
  17. nn.ReLU(),
  18. nn.MaxPool2d(kernel_size=2, stride=2)
  19. )
  20. self.block3 = nn.Sequential(
  21. nn.Conv2d(128, 256, kernel_size=3, padding=1),
  22. nn.ReLU(),
  23. nn.Conv2d(256, 256, kernel_size=3, padding=1),
  24. nn.ReLU(),
  25. nn.Conv2d(256, 256, kernel_size=3, padding=1),
  26. nn.ReLU(),
  27. nn.MaxPool2d(kernel_size=2, stride=2)
  28. )
  29. self.block4 = nn.Sequential(
  30. nn.Conv2d(256, 512, kernel_size=3, padding=1),
  31. nn.ReLU(),
  32. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  33. nn.ReLU(),
  34. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  35. nn.ReLU(),
  36. nn.MaxPool2d(kernel_size=2, stride=2)
  37. )
  38. self.block5 = nn.Sequential(
  39. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  40. nn.ReLU(),
  41. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  42. nn.ReLU(),
  43. nn.Conv2d(512, 512, kernel_size=3, padding=1),
  44. nn.ReLU(),
  45. nn.MaxPool2d(kernel_size=2, stride=2),
  46. nn.AdaptiveAvgPool2d((1, 1))
  47. )
  48. self.dense = nn.Sequential(
  49. nn.Linear(512, 1024),
  50. nn.ReLU(),
  51. nn.Linear(1024, n_categories),
  52. nn.Softmax(dim=0)
  53. )
  54. def forward(self, x):
  55. x = self.block1(x)
  56. x = self.block2(x)
  57. x = self.block3(x)
  58. x = self.block4(x)
  59. x = self.block5(x)
  60. x = torch.flatten(x)
  61. x = self.dense(x)
  62. return x
  63. N_CATEGORIES = 203
  64. pytorch_model = CustomModel(N_CATEGORIES)

It's a loading of weights:

  1. pytorch_model.block1[0].weight.data = torch.from_numpy(np.transpose(weights[0]))
  2. pytorch_model.block1[0].bias.data = torch.from_numpy(weights[1])
  3. pytorch_model.block1[2].weight.data = torch.from_numpy(np.transpose(weights[2]))
  4. pytorch_model.block1[2].bias.data = torch.from_numpy(weights[3])
  5. pytorch_model.block2[0].weight.data = torch.from_numpy(np.transpose(weights[4]))
  6. pytorch_model.block2[0].bias.data = torch.from_numpy(weights[5])
  7. pytorch_model.block2[2].weight.data = torch.from_numpy(np.transpose(weights[6]))
  8. pytorch_model.block2[2].bias.data = torch.from_numpy(weights[7])
  9. pytorch_model.block3[0].weight.data = torch.from_numpy(np.transpose(weights[8]))
  10. pytorch_model.block3[0].bias.data = torch.from_numpy(weights[9])
  11. pytorch_model.block3[2].weight.data = torch.from_numpy(np.transpose(weights[10]))
  12. pytorch_model.block3[2].bias.data = torch.from_numpy(weights[11])
  13. pytorch_model.block3[4].weight.data = torch.from_numpy(np.transpose(weights[12]))
  14. pytorch_model.block3[4].bias.data = torch.from_numpy(weights[13])
  15. pytorch_model.block4[0].weight.data = torch.from_numpy(np.transpose(weights[14]))
  16. pytorch_model.block4[0].bias.data = torch.from_numpy(weights[15])
  17. pytorch_model.block4[2].weight.data = torch.from_numpy(np.transpose(weights[16]))
  18. pytorch_model.block4[2].bias.data = torch.from_numpy(weights[17])
  19. pytorch_model.block4[4].weight.data = torch.from_numpy(np.transpose(weights[18]))
  20. pytorch_model.block4[4].bias.data = torch.from_numpy(weights[19])
  21. pytorch_model.block5[0].weight.data = torch.from_numpy(np.transpose(weights[20]))
  22. pytorch_model.block5[0].bias.data = torch.from_numpy(weights[21])
  23. pytorch_model.block5[2].weight.data = torch.from_numpy(np.transpose(weights[22]))
  24. pytorch_model.block5[2].bias.data = torch.from_numpy(weights[23])
  25. pytorch_model.block5[4].weight.data = torch.from_numpy(np.transpose(weights[24]))
  26. pytorch_model.block5[4].bias.data = torch.from_numpy(weights[25])
  27. pytorch_model.dense[0].weight.data = torch.from_numpy(np.transpose(weights[26]))
  28. pytorch_model.dense[0].bias.data = torch.from_numpy(weights[27])
  29. pytorch_model.dense[2].weight.data = torch.from_numpy(np.transpose(weights[28]))
  30. pytorch_model.dense[2].bias.data = torch.from_numpy(weights[29])

答案2

得分: 0

一个简单的方法是直接将模型从Keras转换为PyTorch,使用ONNX作为中间模型。可以在几个步骤内轻松完成:

步骤1:将Keras模型保存为ONNX

  1. from tensorflow.python.keras import backend as K
  2. from tensorflow.python.keras.models import load_model
  3. import onnx
  4. import keras2onnx
  5. onnx_model_name = 'baselineonnxmodel.onnx'
  6. model = load_model('baselinekerasmodel.h5')
  7. onnx_model = keras2onnx.convert_keras(model, model.name)
  8. onnx.save_model(onnx_model, onnx_model_name)

步骤2:加载ONNX模型并转换为PyTorch。使用pip install onnx2pytorch安装onnx2pytorch。

  1. import onnx
  2. from onnx2pytorch import ConvertModel
  3. onnx_model = onnx.load('baselineonnxmodel.onnx')
  4. pytorch_model = ConvertModel(onnx_model)

现在,您可以使用pytorch_model进行预测。

英文:

A easy way to do it is to convert the model directly from keras to pytorch using onnx as the intermediate model. This can be easily done in a couple of steps:

Step 1: Save Keras model as ONNX

  1. from tensorflow.python.keras import backend as K
  2. from tensorflow.python.keras.models import load_model
  3. import onnx
  4. import keras2onnx
  5. onnx_model_name = 'baselineonnxmodel.onnx'
  6. model = load_model('baselinekerasmodel.h5')
  7. onnx_model = keras2onnx.convert_keras(model, model.name)
  8. onnx.save_model(onnx_model, onnx_model_name)

Step 2: Load ONNX model and convert to pytorch. Install onnx2pytorch using pip install onnx2pytorch

  1. import onnx
  2. from onnx2pytorch import ConvertModel
  3. onnx_model = onnx.load('baselineonnxmodel.onnx')
  4. pytorch_model = ConvertModel(onnx_model)

You can now use the pytorch_model for making predictions.

huangapple
  • 本文由 发表于 2023年7月31日 19:17:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803096.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定