英文:
Assign weights from keras to torch model
问题
我正在制作一个用于检查动画脸部是否相似的项目。我尝试自己训练一个模型,但进展不明显。因此,我决定使用已经训练好的模型并调整它以满足我的需求。我在GitHub上找到了这个模型。
模型结构如下:
N_CATEGORIES = 203
IMAGE_SIZE = 224
input_tensor = Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3))
base_model = VGG16(weights='imagenet', include_top=False,input_tensor=input_tensor)
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(N_CATEGORIES, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
for layer in base_model.layers[:15]:
layer.trainable = False
Keras模型概要如下:
Model: "model_1"
Layer (type) Output Shape Param
input_1 (InputLayer) [(None, 224, 224, 3)] 0
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
global_average_pooling2d_1 (None, 512) 0
(GlobalAveragePooling2D)
dense_1 (Dense) (None, 1024) 525312
dense_2 (Dense) (None, 203) 208075
=================================================================
我下载了这个模型的.hdf5文件,但我无法将其转换为.pt格式。我在PyTorch中创建了类似于VGG16的结构:
import torch
import torch.nn as nn
class CustomModel(nn.Module):
def __init__(self):
super(CustomModel, self).__init__()
self.block1 = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
# 你可以继续添加其他块...
self.fc1 = nn.Linear(512, 1024)
self.fc2 = nn.Linear(1024, 203)
def forward(self, x):
x = self.block1(x)
# 你可以继续添加其他块...
x = self.fc1(x)
x = self.fc2(x)
return x
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:
N_CATEGORIES = 203
IMAGE_SIZE = 224
input_tensor = Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3))
base_model = VGG16(weights='imagenet', include_top=False,input_tensor=input_tensor)
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(N_CATEGORIES, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
for layer in base_model.layers[:15]:
layer.trainable = False
Keras model summary:
Model: "model_1"
Layer (type) Output Shape Param
input_1 (InputLayer) [(None, 224, 224, 3)] 0
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
global_average_pooling2d_1 (None, 512) 0
(GlobalAveragePooling2D)
dense_1 (Dense) (None, 1024) 525312
dense_2 (Dense) (None, 203) 208075
=================================================================
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:
import torch
import torch.nn as nn
class CustomModel(nn.Module):
def __init__(self):
super(CustomModel, self).__init__()
self.block1 = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block2 = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block3 = nn.Sequential(
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block4 = nn.Sequential(
nn.Conv2d(256, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block5 = nn.Sequential(
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.global_avg_pool = nn.AdaptiveAvgPool2d((1, 1))
self.fc1 = nn.Linear(512, 1024)
self.fc2 = nn.Linear(1024, 203)
def forward(self, x):
x = self.block1(x)
x = self.block2(x)
x = self.block3(x)
x = self.block4(x)
x = self.block5(x)
x = self.global_avg_pool(x)
x = torch.flatten(x, 1)
x = self.fc1(x)
x = self.fc2(x)
return x
pytorch_model = CustomModel()
I imported weight to keras:
from keras.models import load_model
model = load_model('animeface_vgg16.hdf5')
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
找到了答案。以下是模型结构:
```python
import torch
import torch.nn as nn
class CustomModel(nn.Module):
def __init__(self, n_categories):
super(CustomModel, self).__init__()
self.block1 = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block2 = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block3 = nn.Sequential(
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block4 = nn.Sequential(
nn.Conv2d(256, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block5 = nn.Sequential(
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.AdaptiveAvgPool2d((1, 1))
)
self.dense = nn.Sequential(
nn.Linear(512, 1024),
nn.ReLU(),
nn.Linear(1024, n_categories),
nn.Softmax(dim=0)
)
def forward(self, x):
x = self.block1(x)
x = self.block2(x)
x = self.block3(x)
x = self.block4(x)
x = self.block5(x)
x = torch.flatten(x)
x = self.dense(x)
return x
N_CATEGORIES = 203
pytorch_model = CustomModel(N_CATEGORIES)
加载权重:
pytorch_model.block1[0].weight.data = torch.from_numpy(np.transpose(weights[0]))
pytorch_model.block1[0].bias.data = torch.from_numpy(weights[1])
pytorch_model.block1[2].weight.data = torch.from_numpy(np.transpose(weights[2]))
pytorch_model.block1[2].bias.data = torch.from_numpy(weights[3])
pytorch_model.block2[0].weight.data = torch.from_numpy(np.transpose(weights[4]))
pytorch_model.block2[0].bias.data = torch.from_numpy(weights[5])
pytorch_model.block2[2].weight.data = torch.from_numpy(np.transpose(weights[6]))
pytorch_model.block2[2].bias.data = torch.from_numpy(weights[7])
pytorch_model.block3[0].weight.data = torch.from_numpy(np.transpose(weights[8]))
pytorch_model.block3[0].bias.data = torch.from_numpy(weights[9])
pytorch_model.block3[2].weight.data = torch.from_numpy(np.transpose(weights[10]))
pytorch_model.block3[2].bias.data = torch.from_numpy(weights[11])
pytorch_model.block3[4].weight.data = torch.from_numpy(np.transpose(weights[12]))
pytorch_model.block3[4].bias.data = torch.from_numpy(weights[13])
pytorch_model.block4[0].weight.data = torch.from_numpy(np.transpose(weights[14]))
pytorch_model.block4[0].bias.data = torch.from_numpy(weights[15])
pytorch_model.block4[2].weight.data = torch.from_numpy(np.transpose(weights[16]))
pytorch_model.block4[2].bias.data = torch.from_numpy(weights[17])
pytorch_model.block4[4].weight.data = torch.from_numpy(np.transpose(weights[18]))
pytorch_model.block4[4].bias.data = torch.from_numpy(weights[19])
pytorch_model.block5[0].weight.data = torch.from_numpy(np.transpose(weights[20]))
pytorch_model.block5[0].bias.data = torch.from_numpy(weights[21])
pytorch_model.block5[2].weight.data = torch.from_numpy(np.transpose(weights[22]))
pytorch_model.block5[2].bias.data = torch.from_numpy(weights[23])
pytorch_model.block5[4].weight.data = torch.from_numpy(np.transpose(weights[24]))
pytorch_model.block5[4].bias.data = torch.from_numpy(weights[25])
pytorch_model.dense[0].weight.data = torch.from_numpy(np.transpose(weights[26]))
pytorch_model.dense[0].bias.data = torch.from_numpy(weights[27])
pytorch_model.dense[2].weight.data = torch.from_numpy(np.transpose(weights[28]))
pytorch_model.dense[2].bias.data = torch.from_numpy(weights[29])
英文:
Found an answer by myself. Here is a model structure:
import torch
import torch.nn as nn
class CustomModel(nn.Module):
def __init__(self, n_categories):
super(CustomModel, self).__init__()
self.block1 = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block2 = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block3 = nn.Sequential(
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block4 = nn.Sequential(
nn.Conv2d(256, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.block5 = nn.Sequential(
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.AdaptiveAvgPool2d((1, 1))
)
self.dense = nn.Sequential(
nn.Linear(512, 1024),
nn.ReLU(),
nn.Linear(1024, n_categories),
nn.Softmax(dim=0)
)
def forward(self, x):
x = self.block1(x)
x = self.block2(x)
x = self.block3(x)
x = self.block4(x)
x = self.block5(x)
x = torch.flatten(x)
x = self.dense(x)
return x
N_CATEGORIES = 203
pytorch_model = CustomModel(N_CATEGORIES)
It's a loading of weights:
pytorch_model.block1[0].weight.data = torch.from_numpy(np.transpose(weights[0]))
pytorch_model.block1[0].bias.data = torch.from_numpy(weights[1])
pytorch_model.block1[2].weight.data = torch.from_numpy(np.transpose(weights[2]))
pytorch_model.block1[2].bias.data = torch.from_numpy(weights[3])
pytorch_model.block2[0].weight.data = torch.from_numpy(np.transpose(weights[4]))
pytorch_model.block2[0].bias.data = torch.from_numpy(weights[5])
pytorch_model.block2[2].weight.data = torch.from_numpy(np.transpose(weights[6]))
pytorch_model.block2[2].bias.data = torch.from_numpy(weights[7])
pytorch_model.block3[0].weight.data = torch.from_numpy(np.transpose(weights[8]))
pytorch_model.block3[0].bias.data = torch.from_numpy(weights[9])
pytorch_model.block3[2].weight.data = torch.from_numpy(np.transpose(weights[10]))
pytorch_model.block3[2].bias.data = torch.from_numpy(weights[11])
pytorch_model.block3[4].weight.data = torch.from_numpy(np.transpose(weights[12]))
pytorch_model.block3[4].bias.data = torch.from_numpy(weights[13])
pytorch_model.block4[0].weight.data = torch.from_numpy(np.transpose(weights[14]))
pytorch_model.block4[0].bias.data = torch.from_numpy(weights[15])
pytorch_model.block4[2].weight.data = torch.from_numpy(np.transpose(weights[16]))
pytorch_model.block4[2].bias.data = torch.from_numpy(weights[17])
pytorch_model.block4[4].weight.data = torch.from_numpy(np.transpose(weights[18]))
pytorch_model.block4[4].bias.data = torch.from_numpy(weights[19])
pytorch_model.block5[0].weight.data = torch.from_numpy(np.transpose(weights[20]))
pytorch_model.block5[0].bias.data = torch.from_numpy(weights[21])
pytorch_model.block5[2].weight.data = torch.from_numpy(np.transpose(weights[22]))
pytorch_model.block5[2].bias.data = torch.from_numpy(weights[23])
pytorch_model.block5[4].weight.data = torch.from_numpy(np.transpose(weights[24]))
pytorch_model.block5[4].bias.data = torch.from_numpy(weights[25])
pytorch_model.dense[0].weight.data = torch.from_numpy(np.transpose(weights[26]))
pytorch_model.dense[0].bias.data = torch.from_numpy(weights[27])
pytorch_model.dense[2].weight.data = torch.from_numpy(np.transpose(weights[28]))
pytorch_model.dense[2].bias.data = torch.from_numpy(weights[29])
答案2
得分: 0
一个简单的方法是直接将模型从Keras转换为PyTorch,使用ONNX作为中间模型。可以在几个步骤内轻松完成:
步骤1:将Keras模型保存为ONNX
from tensorflow.python.keras import backend as K
from tensorflow.python.keras.models import load_model
import onnx
import keras2onnx
onnx_model_name = 'baselineonnxmodel.onnx'
model = load_model('baselinekerasmodel.h5')
onnx_model = keras2onnx.convert_keras(model, model.name)
onnx.save_model(onnx_model, onnx_model_name)
步骤2:加载ONNX模型并转换为PyTorch。使用pip install onnx2pytorch
安装onnx2pytorch。
import onnx
from onnx2pytorch import ConvertModel
onnx_model = onnx.load('baselineonnxmodel.onnx')
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
from tensorflow.python.keras import backend as K
from tensorflow.python.keras.models import load_model
import onnx
import keras2onnx
onnx_model_name = 'baselineonnxmodel.onnx'
model = load_model('baselinekerasmodel.h5')
onnx_model = keras2onnx.convert_keras(model, model.name)
onnx.save_model(onnx_model, onnx_model_name)
Step 2: Load ONNX model and convert to pytorch. Install onnx2pytorch using pip install onnx2pytorch
import onnx
from onnx2pytorch import ConvertModel
onnx_model = onnx.load('baselineonnxmodel.onnx')
pytorch_model = ConvertModel(onnx_model)
You can now use the pytorch_model
for making predictions.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论