来自keras的theano错误

theano error from keras

我是 运行 一个 keras 脚本(在我的脚本中没有直接调用 theano)并且我收到以下错误:

TypeError: ('An update must have the same type as the original shared                     
variable (shared_var=<TensorType(float32, matrix)>, 
shared_var.type=TensorType(float32, matrix),     
update_val=Elemwise{add,no_inplace}.0, 
update_val.type=TensorType(float64, matrix)).', 
'If the difference is related to the broadcast pattern, 
you can call the tensor.unbroadcast(var, axis_to_unbroadcast[, ...])
function to remove broadcastable dimensions.')

我直接从 运行 theano 看到了错误,但不是通过 keras。不确定我应该做什么,因为我没有直接处理张量。

问题是 keras 版本发生了变化(我目前使用的是 keras 0.3.2 和 theano 0.8.0),以前很好用的新 keras 版本不能很好地工作。

以下为原代码,修复见下文

from keras.models import Sequential
import keras.optimizers
from keras.layers.core import Dense, Dropout
from keras.layers.normalization import BatchNormalization
from keras.layers.advanced_activations import PReLU
from keras.layers.core import Activation
from keras.optimizers import SGD, Adam

from sklearn.preprocessing import StandardScaler
from sklearn.base import BaseEstimator, RegressorMixin

class NnRegression(BaseEstimator, RegressorMixin):
        def __init__(self, apply_standart_scaling=True,
             dropx=[0.2, 0.5, 0.5], nb_neuronx=[50, 30], nb_epoch=105, validation_split=0.,
             verbose=1):
        self.apply_standart_scaling = apply_standart_scaling
        self.dropx = dropx
        self.nb_neuronx = nb_neuronx
        self.nb_epoch = nb_epoch
        self.validation_split = validation_split
        self.verbose = verbose

    def fit(self, X, y):

        nb_features = X.shape[1]
        self.standart_scaling = StandardScaler() if self.apply_standart_scaling else None

        if self.standart_scaling:
            X = self.standart_scaling.fit_transform(X)

        model = Sequential()
        model.add(Dropout(input_shape = (nb_features,),p= self.dropx[0]))
        model.add(Dense(output_dim = self.nb_neuronx[0], init='glorot_uniform'))
        model.add(PReLU())
        model.add(BatchNormalization(self.nb_neuronx[0],)))
        model.add(Dropout(self.dropx[1]))

        model.add(Dense(self.nb_neuronx[1], init='glorot_uniform'))
        model.add(PReLU())
        model.add(BatchNormalization(self.nb_neuronx[0],)))
        model.add(Dropout(self.dropx[2]))

        model.add(Dense(1, init='glorot_uniform'))

        nn_verbose = 1 if self.verbose>0 else 0
        optz = keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
        model.compile(optimizer=Adam(),loss='mse')
        model.fit(X, y, batch_size=16,
              nb_epoch=self.nb_epoch, validation_split=self.validation_split, verbose=nn_verbose)

        self.model = model

    def predict(self, X):
        if self.standart_scaling:
            X = self.standart_scaling.transform(X)
        return self.model.predict_proba(X, verbose=0)

嗯,原来是这行代码有问题:

model.add(BatchNormalization(self.nb_neuronx[0],)))

实际上应该是:

model.add(BatchNormalization())

因为神经元的数量与归一化层无关(但这在以前的 keras 版本中没有影响)。

这显然会导致 theano 生成不是 float32 而是 float64 的新权重,这会触发上面的消息。