Cómo reemplazar la función de pérdida durante el entrenamiento tensorflow.keras

Francis Escala:

Quiero reemplazar la función de pérdida relacionada con mi red neuronal durante el entrenamiento, se trata de la red:

model = tensorflow.keras.models.Sequential()
        model.add(tensorflow.keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=input_shape))
        model.add(tensorflow.keras.layers.Conv2D(64, (3, 3), activation="relu"))
        model.add(tensorflow.keras.layers.MaxPooling2D(pool_size=(2, 2)))
        model.add(tensorflow.keras.layers.Dropout(0.25))
        model.add(tensorflow.keras.layers.Flatten())
        model.add(tensorflow.keras.layers.Dense(128, activation="relu"))
        model.add(tensorflow.keras.layers.Dropout(0.5))
        model.add(tensorflow.keras.layers.Dense(output_classes, activation="softmax"))
        model.compile(loss=tensorflow.keras.losses.categorical_crossentropy, optimizer=tensorflow.keras.optimizers.Adam(0.001), metrics=['accuracy'])
        history = model.fit(x_train, y_train, batch_size=128, epochs=5, validation_data=(x_test, y_test))

por lo que ahora quiero cambiar tensorflow.keras.losses.categorical_crossentropycon otro, así que hice esto:

model.compile(loss=tensorflow.keras.losses.mse, optimizer=tensorflow.keras.optimizers.Adam(0.001), metrics=['accuracy'])
    history = model.fit(x_improve, y_improve, epochs=1, validation_data=(x_test, y_test)) #FIXME bug during training

pero tengo este error:

ValueError: No gradients provided for any variable: ['conv2d/kernel:0', 'conv2d/bias:0', 'conv2d_1/kernel:0', 'conv2d_1/bias:0', 'dense/kernel:0', 'dense/bias:0', 'dense_1/kernel:0', 'dense_1/bias:0'].

¿Por qué? ¿Cómo puedo arreglarlo? Hay otra manera de cambiar la función de pérdida?

Gracias

Edward Guerriero:

Por lo tanto, una respuesta directa que daría es: cambiar a pytorch si quieres jugar este tipo de juegos. Dado que en pytorch a definir sus funciones de formación y evaluación, sólo se necesita una sentencia if para pasar de una función de pérdida a otro.

Además, veo en su código que desea cambiar de cross_entropy a mean_square_error, el primero es adecuado para la clasificación de este último para la regresión, así que esto no es realmente algo que puede hacer, en el código que sigue Cambié de error cuadrático medio de Medio error logarítmica cuadrado, que son tanto la pérdida adecuado para la regresión.

A pesar de otras respuestas ofrece soluciones a su pregunta (ver el cambio de pérdida de función-dinámicamente durante el entrenamiento ) no está claro ya sea que se puede confiar o no los resultados. Algunas personas encuentran que incluso con una función personalizada a veces la formación torreón Keras con la primera pérdida.

Solución:

Mi solución se basa en train_on_batch, lo que nos permite entrenar un modelo en un bucle y por lo tanto dejar de entrenar siempre que preferimos volver a compilar el modelo con una nueva función de pérdida. Tenga en cuenta que recompilar el modelo no restablece los pesos (ver: que falla la compilación de un modelo re-inicializar los pesos? ).

El conjunto de datos se puede encontrar aquí Boston conjunto de datos de vivienda

# Regression Example With Boston Dataset: Standardized and Larger
from pandas import read_csv
from keras.models import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split
from keras.losses import mean_squared_error, mean_squared_logarithmic_error
from matplotlib import pyplot
import matplotlib.pyplot as plt

# load dataset
dataframe = read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values

# split into input (X) and output (Y) variables
X = dataset[:,0:13]
y = dataset[:,13]

trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.33, random_state=42)

# create model
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(6, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))

batch_size = 25

# have to define manually a dict to store all epochs scores 
history = {}
history['history'] = {}
history['history']['loss'] = []
history['history']['mean_squared_error'] = []
history['history']['mean_squared_logarithmic_error'] = []
history['history']['val_loss'] = []
history['history']['val_mean_squared_error'] = []
history['history']['val_mean_squared_logarithmic_error'] = []

# first compiling with mse
model.compile(loss='mean_squared_error', optimizer='adam', metrics=[mean_squared_error, mean_squared_logarithmic_error])

# define number of iterations in training and test
train_iter = round(trainX.shape[0]/batch_size)
test_iter = round(testX.shape[0]/batch_size)

for epoch in range(2):

    # train iterations 
    loss, mse, msle = 0, 0, 0
    for i in range(train_iter):

        start = i*batch_size
        end = i*batch_size + batch_size
        batchX = trainX[start:end,]
        batchy = trainy[start:end,]

        loss_, mse_, msle_ = model.train_on_batch(batchX,batchy)

        loss += loss_
        mse += mse_
        msle += msle_

    history['history']['loss'].append(loss/train_iter)
    history['history']['mean_squared_error'].append(mse/train_iter)
    history['history']['mean_squared_logarithmic_error'].append(msle/train_iter)

    # test iterations 
    val_loss, val_mse, val_msle = 0, 0, 0
    for i in range(test_iter):

        start = i*batch_size
        end = i*batch_size + batch_size
        batchX = testX[start:end,]
        batchy = testy[start:end,]

        val_loss_, val_mse_, val_msle_ = model.test_on_batch(batchX,batchy)

        val_loss += val_loss_
        val_mse += val_mse_
        val_msle += msle_

    history['history']['val_loss'].append(val_loss/test_iter)
    history['history']['val_mean_squared_error'].append(val_mse/test_iter)
    history['history']['val_mean_squared_logarithmic_error'].append(val_msle/test_iter)

# recompiling the model with new loss
model.compile(loss='mean_squared_logarithmic_error', optimizer='adam', metrics=[mean_squared_error, mean_squared_logarithmic_error])

for epoch in range(2):

    # train iterations 
    loss, mse, msle = 0, 0, 0
    for i in range(train_iter):

        start = i*batch_size
        end = i*batch_size + batch_size
        batchX = trainX[start:end,]
        batchy = trainy[start:end,]

        loss_, mse_, msle_ = model.train_on_batch(batchX,batchy)

        loss += loss_
        mse += mse_
        msle += msle_

    history['history']['loss'].append(loss/train_iter)
    history['history']['mean_squared_error'].append(mse/train_iter)
    history['history']['mean_squared_logarithmic_error'].append(msle/train_iter)

    # test iterations 
    val_loss, val_mse, val_msle = 0, 0, 0
    for i in range(test_iter):

        start = i*batch_size
        end = i*batch_size + batch_size
        batchX = testX[start:end,]
        batchy = testy[start:end,]

        val_loss_, val_mse_, val_msle_ = model.test_on_batch(batchX,batchy)

        val_loss += val_loss_
        val_mse += val_mse_
        val_msle += msle_

    history['history']['val_loss'].append(val_loss/test_iter)
    history['history']['val_mean_squared_error'].append(val_mse/test_iter)
    history['history']['val_mean_squared_logarithmic_error'].append(val_msle/test_iter)

# Some plots to check what is going on   
# loss function 
pyplot.subplot(311)
pyplot.title('Loss')
pyplot.plot(history['history']['loss'], label='train')
pyplot.plot(history['history']['val_loss'], label='test')
pyplot.legend()

# Only mean squared error 
pyplot.subplot(312)
pyplot.title('Mean Squared Error')
pyplot.plot(history['history']['mean_squared_error'], label='train')
pyplot.plot(history['history']['val_mean_squared_error'], label='test')
pyplot.legend()

# Only mean squared logarithmic error 
pyplot.subplot(313)
pyplot.title('Mean Squared Logarithmic Error')
pyplot.plot(history['history']['mean_squared_logarithmic_error'], label='train')
pyplot.plot(history['history']['val_mean_squared_logarithmic_error'], label='test')
pyplot.legend()
plt.tight_layout()
pyplot.show()

El gráfico resultante confirman que la función de pérdida está cambiando después de la segunda época:

introducir descripción de la imagen aquí

La caída en la función de pérdida es debido al hecho de que el modelo está cambiando de error cuadrático medio normal a la logarítmica, que tiene valores mucho más bajos. Impresión de los resultados también demuestra que las pérdidas usada realmente cambió:

print(history['history']['loss'])
[599.5209197998047, 570.4041115897043, 3.8622902120862688, 2.1578191178185597]
print(history['history']['mean_squared_error'])
[599.5209197998047, 570.4041115897043, 510.29034205845426, 425.32058388846264]
print(history['history']['mean_squared_logarithmic_error'])
[8.624503476279122, 6.346359729766846, 3.8622902120862688, 2.1578191178185597]

En las dos primeras épocas de la pérdida de los valores son iguales a las de mean_square_error y durante el tercer y cuarto épocas los valores se hace igual a las de mean_square_logarithmic_error, que es la nueva pérdida que se haya ajustado. Por lo tanto, parece que el uso de train_on_batch permite función de pérdida de cambio, sin embargo, quiero subrayar una vez más que esto es básicamente lo que uno debe hacer en pytoch para lograr los mismos resultados, con la diferencia de que el comportamiento de pytorch (en este escenario y en mi opinión) es más fiable.

Supongo que te gusta

Origin http://10.200.1.11:23101/article/api/json?id=408721&siteId=1
Recomendado
Clasificación