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

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

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.

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:

确定