注意:下面给出的所有代码都可以正常工作,并且给出很好的结果,但是问题是我无法保存模型。您可以运行下面给出的所有代码来在保存模型的同时纠正错误
我最近学习了如何构建自定义图层和模型。我将自定义图层构建为:
class FullyConnected(Layer):
'''
Fully Connected or Dense layer
'''
def __init__(self,units=16,w_init='he_uniform',b_init='zeros',activation=None,**kwargs):
'''
Constructor of the class
args:
units: {int} number of neurons to use
w_init = {string/callable} weight initializer
b_init = {string/callable/None} bias initializer. None if no bias is included
activation: {string} activation function to use
**kwargs: {dict} keyword arg for the parent class
'''
super(FullyConnected,self).__init__(**kwargs)
self.units = units
self.w_init = w_init
self.b_init = b_init
self.activation = tf.keras.activations.get(activation) # gives a respective callable. None gives linear
def build(self,input_shape):
'''
Assign weights to the layer dynamically. Base layer method
'''
self.w = self.add_weight(shape=(input_shape[-1],self.units),initializer=self.w_init,trainable=True)
if self.b_init:
self.b = self.add_weight(shape=(self.units,),initializer=self.b_init,trainable=True)
def call(self,input_tensor):
'''
Forward Pass. Part of Base layer
'''
result = tf.matmul(input_tensor,self.w)
if self.b_init:
result = result + self.b
if self.activation:
result = self.activation(result)
return result
def compute_output_shape(self,input_shape):
'''
Method of base class which computes the shape of output.
compute_output_shape is not needed unless the Layer is Dynamic
args:
input_shape: (tuple) shape of incoming tensor
out:
out_shape: (tuple) shape of resulting tensor
'''
out_shape = list(input_shape) # because we can not append to tuple
out_shape[-1] = self.units # replace the incoming feature dimension to outgoing
return tuple(out_shape) # a tuple is needed for shape
def get_config(self):
config = super(FullyConnected,self).get_config() # get config of the base Layer class
config.update({'units':self.units,'activation':tf.keras.activations.serialize(self.activation)})
# you need to serialise the callable activation function
return config
我创建了一个自定义模型:
class ClassificationModel(Model):
'''
A model that performs simple classification where each input can belong to Only 1 class
'''
def __init__(self,input_shape,layers_units=[8,],classes=2,activation='relu',**kwargs):
'''
Constructor of the class to get initial arguments
args:
input_shape = {tuple} shape of incoming data
layer_units: {list} units to use for each layer
classes: {int} Number of classes either binary or multiclass
activation = {string/callable} activation function to use
'''
super(ClassificationModel,self).__init__(**kwargs)
assert len(layers_units)>=1 , "units must be >=1"
assert classes>=2, "classes must be >=2"
self.in_shape = input_shape
self.units = layers_units
self.classes = classes
self.activation = activation
self.in_layer = FullyConnected(self.units[0],activation=self.activation,
name='input_layer',
input_shape=self.in_shape)
# input_shape is a parameter of base class
self.middle_layers = [] # middle layers do not have Input_shape
for i in range(1,len(self.units)):
self.middle_layers.append(FullyConnected(self.units[i],activation=self.activation))
if self.classes == 2:
self.out_layer = FullyConnected(1,activation='sigmoid',name='output_layer')
else:
self.out_layer = FullyConnected(self.classes,activation='softmax',name='output_layer')
def call(self,tensor):
'''
Perform a forward pass operation
'''
x = self.in_layer(tensor)
for layer in self.middle_layers:
x = layer(x)
probs = self.out_layer(x)
return probs
我训练了模型并表现良好。
wine = load_wine() # sklearn dataset
X = wine['data']
y = wine['target']
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=13)
model = ClassificationModel(input_shape=X_train.shape,layers_units=[64,32,32],classes=3,activation='relu')
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
history = model.fit(X_train,y_train,epochs=300,validation_data=(X_test,y_test),batch_size=32)
但是当我尝试使用model.save('model.tf',save_format='tf')
保存模型时,它给我一个错误:
AttributeError: 'NoneType' object has no attribute 'replace'
以及当我使用model.save_weights('model_weight',save_format='h5')
时
它会抛出:
OSError: Unable to create link (name already exists)
我已多次检查是否存在不存在该名称的文件。