Pytorch DataParallel model load with map_location - pytorch

Model saved with
net= Net()
model= torch.nn.DataParallel(net)
############################
# Training
############################
torch.save(model,'./model_shear_pre.pkl')
Model loading with
net = Net()
model = torch.nn.DataParallel(net, device_ids=[0,1])
model = torch.load('./model_shear_finish.pkl', map_location={'cuda:0':'cuda:0', 'cuda:1':'cuda:0', 'cuda:2':'cuda:1', 'cuda:3':'cuda:1'})
The prob is that when training I used a machine with 4 GPU, after saving the model, I would like to test it on a new machine with only 2 GPU.
After loading the saved model, I expect the model's device_ids would be [0,1], but it still be [0,1,2,3] which is the old setting. Is there anything wrong when saving or loading?

You should save the weights instead of the whole model.
net = Net()
model = torch.nn.DataParallel(net)
############################
# Training
############################
torch.save(model.state_dict(),'./model_shear_pre.pkl')
Then load the weight in CPU before move to all GPU
net = Net()
weights = torch.load('./model_shear_finish.pkl', map_location='cpu')
net.load_state_dict(weights)
model = torch.nn.DataParallel(net, device_ids=[0,1])
But if you have an already trained model that is saved using the whole model instead of just weights this might also work
net = torch.load('./model_shear_finish.pkl', map_location='cpu')
model = torch.nn.DataParallel(net, device_ids=[0,1])
I still recommend save only weights though. Saving and loading the whole model can really screw you up because you have to import the model the exact same way both in the save and load. And a lot of time that's a tricky thing to do. Like
train.py
from nets import Net
net = Net()
torch.save(net, './model_shear_finish.pkl')
inference.py
# this won't work
import nets
torch.load('./model_shear_finish.pkl', map_location='cpu')
# this will work
from nets import Net
torch.load('./model_shear_finish.pkl', map_location='cpu')

Related

How to load BertforSequenceClassification models weights into BertforTokenClassification model?

Initially, I have a fine-tuned BERT base cased model using a text classification dataset and I have used BertforSequenceClassification class for this.
from transformers import BertForSequenceClassification, AdamW, BertConfig
# Load BertForSequenceClassification, the pretrained BERT model with a single
# linear classification layer on top.
model = BertForSequenceClassification.from_pretrained(
"bert-base-uncased", # Use the 12-layer BERT model, with an uncased vocab.
num_labels = 2, # The number of output labels--2 for binary classification.
# You can increase this for multi-class tasks.
output_attentions = False, # Whether the model returns attentions weights.
output_hidden_states = False, # Whether the model returns all hidden-states.
)
Now I want to use this fine-tuned BERT model weights for Named Entity Recognition and I have to use BertforTokenClassification class for this. I'm unable to figure out how to load the fine-tuned BERT model weights into the new model created using BertforTokenClassification.
Thanks in advance.......................
You can get weights from the bert inside the first model and load into the bert inside the second:
new_model = BertForTokenClassification(config=config)
new_model.bert.load_state_dict(model.bert.state_dict())
This worked for me
new_model = BertForTokenClassification.from_pretrained('/config path')
new_model.bert.load_state_dict(model.bert.state_dict())

Accessing a pretrained model's weights (names and values) in TensorFlow

Quantitative analysis of Neural Networks needs load all variables first in
TensorFlow. So I import the SSDLite MobileNet v2 model's checkpoint and restore weights. But I can not get its weights or variables by using some functions, such as get_all_coolection_keys, get_collection. The code snippet as follows:
import tensorflow as tf
import numpy as np
model_dir = 'ssdlite_mobilenet_v2_coco_2018_05_09'
checkpoint = tf.train.get_checkpoint_state(model_dir)
input_checkpoint = checkpoint.model_checkpoint_path # ssdlite_mobilenet_v2_coco_2018_05_09/model.ckpt
sess = tf.Session()
tf.reset_default_graph()
saver = tf.train.import_meta_graph(input_checkpoint + '.meta')
graph = tf.get_default_graph()
saver.restore(sess, input_checkpoint)
# INFO:tensorflow:Restoring parameters from ssdlite_mobilenet_v2_coco_2018_05_09/model.ckpt
graph_collections_keys = graph.get_all_collection_keys()
print(graph_collections_keys) # []
hyperparameters = tf.get_collection('hyperparameters')
print(len(hyperparameters)) # 0
model_variables = tf.get_collection(tf.GraphKeys.MODEL_VARIABLES)
print(len(model_variables)) # 0
So, how to access a pretrained model's weights (names and values) in TensorFlow?
pal, you can't restore variable name, weights is as far as you go. Also in tensorflow or in your code in general , the only option you got for restoring is saver . It also depends what kind of data you wanna restore if it's .npy file then np.load will do.

Modify layers in resnet model

I am trying to train resnet50 model for image classification problem. I have loaded the pretrained 'imagenet' weights before training the model on the dataset I have. I want to insert a layer (mean subtraction layer) in-between the input layer and the first convolutiuon layer.
model = ResNet50(weights='imagenet')
def mean_subtract(img):
img = T.set_subtensor(img[:,0,:,:],img[:,0,:,:] - 123.68)
img = T.set_subtensor(img[:,1,:,:],img[:,1,:,:] - 116.779)
img = T.set_subtensor(img[:,2,:,:],img[:,2,:,:] - 103.939)
return img / 255.0
I want to insert inputs = Lambda(mean_subtract, name='mean_subtraction')(inputs) next to the input layer and connect this to the first convolution layer of resnet model without losing the weights saved.
How do I do that?
Thanks!
Quick answer (Seems better than adding the function to the model)
Use the preprocessing function as described here: preprocessing images generated using keras function ImageDataGenerator() to train resnet50 model
Long answer
Since your function doesn't change shapes, you can put it in an outer model without changing the Resnet model (changing models may not be so simple, I always try to mount new models with parts from other models if needed).
resnet_model = ResNet50(weights='imagenet')
inputs = Input((None,None,3))
#it seems you're using (3,None,None) instead.
#choose based on your "data_format", which by default is channels_last
outputs = Lambda(mean_subtract,output_shape=not_necessary_with_tensorflow)(inputs)
outputs = resnet_model(outputs)
model = Model(inputs, outputs)

Keras Model Accuracy differs after loading the same saved model

I trained a Keras Sequential Model and Loaded the same later. Both the model are giving different accuracy.
I have came across a similar question but was not able solve the problem.
Sample Code :
Loading and Traing the model
model = gensim.models.FastText.load('abc.simple')
X,y = load_data()
Vectors = np.array(vectors(X))
X_train, X_test, y_train, y_test = train_test_split(Vectors, np.array(y),
test_size = 0.3, random_state = 0)
X_train = X_train.reshape(X_train.shape[0],100,max_tokens,1)
X_test = X_test.reshape(X_test.shape[0],100,max_tokens,1)
data for input to our model
print(X_train.shape)
model2 = train()
score = model2.evaluate(X_test, y_test, verbose=0)
print(score)
Training Accuracy is 90%.
Saved the Model
# Saving Model
model_json = model2.to_json()
with open("model_architecture.json", "w") as json_file:
json_file.write(model_json)
model2.save_weights("model_weights.h5")
print("Saved model to disk")
But after I restarted the kernel and just loaded the saved model and runned it on same set of data, accuracy got reduced.
#load json and create model
json_file = open('model_architecture.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
#load weights into new model
loaded_model.load_weights("model_weights.h5")
print("Loaded model from disk")
# evaluate loaded model on test data
loaded_model.compile(loss='binary_crossentropy', optimizer='rmsprop',
metrics=['accuracy'])
score = loaded_model.evaluate(X_test, y_test, verbose=0)
print(score)
Accuracy got reduced to 75% on the same set of data.
How to make it consistent ?
I have tried the following but of no help :
from keras.backend import manual_variable_initialization
manual_variable_initialization(True)
Even , I saved the whole model at once( weights and architecture) but was not able to solve this issue
Not sure, if your issue has been solved but for future comers.
I had exactly the same problem with saving and loading the weights. So on loading the model the accuracy and loss were changed greatly from 68% accuracy to 2 %. In my experiment, I am using Tensorflow as backend with Keras model layers Embedding, LSTM and Dense. My issue got solved by fixing the seed for keras which uses NumPy random generator and since I am using Tensorflow as backend, I also fixed the seed for it.
These are the lines I added at the top of my file where the model is also defined.
from numpy.random import seed
seed(42)# keras seed fixing
import tensorflow as tf
tf.random.set_seed(42)# tensorflow seed fixing
I hope this helps.
For more information have a look at this- https://machinelearningmastery.com/reproducible-results-neural-networks-keras/
I had the same problem due to a silly mistake of mine - after loading the model I had in my data generator the shuffle option (useful for the training) turned to True instead of False. After changing it to False the model predicted as expected. It would be nice if keras could take care of this automatically. This is my critical code part:
pred_generator = pred_datagen.flow_from_directory(
directory='./ims_dir',
target_size=(100, 100),
color_mode="rgb",
batch_size=1,
class_mode="categorical",
shuffle=False,
)
model = load_model(logpath_ms)
pred=model.predict_generator(pred_generator, steps = N, verbose=1)
My code worked when I scaled my dataset before reevaluating the model. I did this treatment before saving the model and had forgotten to repeat this procedure when I opened the model and wanted to evaluate it again. After I did that, the accuracy value appeared as it should \o/
model_saved = keras.models.load_model('tuned_cnn_1D_HAR_example.h5')
trainX, trainy, testX, testy = load_dataset()
trainX, testX = scale_data(trainX, testX, True)
score = model_saved.evaluate(testX, testy, verbose=0)
print("%s: %.2f%%" % (model_saved.metrics_names[1], score[1]*100))
inside of my function scale_data I used StandardScaler()

Keras loaded model input change

Do you have any idea of an easy way to modify input image size of a saved model in Keras? For example the training input image size is 32x32, but in test I would like to input the full image 180x180. The model has been saved and at test loaded as the following:
json_file = open('autoencoder64a.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
loaded_model.load_weights("autoencoder64a.h5")
Many thanks,
Tina
Is this a fully convolutional net? Otherwise you will not be able to reuse it with different input size, as this will change the number of weights in the non-convolutional layers.
If it is indeed a FCN, you only need to change the first and last line in the code defining the model:
input_layer = Input((180,180))
#All other layers copied here from your old model,
#ending with 'last_layer =...'
new_model = Model(input_layer, last_layer)

Resources