Tensorflow 不应该';相同的神经网络权重是否会产生相同的结果?

Tensorflow 不应该';相同的神经网络权重是否会产生相同的结果?,tensorflow,neural-network,pytorch,Tensorflow,Neural Network,Pytorch,因此,作为研究的一部分,我正在使用不同的深度学习框架,并观察到一些奇怪的现象(至少我无法解释其原因) 我在Tensorflow中训练了一个相当简单的MLP模型(在mnist数据集上),提取了训练过的权重,在PyTorch中创建了相同的模型架构,并将训练过的权重应用于PyTorch模型。现在我的期望是从Tensorflow和PyTorch模型中获得相同的测试精度,但事实并非如此。我得到了不同的结果 所以我的问题是:如果一个模型被训练到某个最优值,那么训练的权重不应该在每次对同一个数据集进行测试时产

因此,作为研究的一部分,我正在使用不同的深度学习框架,并观察到一些奇怪的现象(至少我无法解释其原因)

我在Tensorflow中训练了一个相当简单的MLP模型(在mnist数据集上),提取了训练过的权重,在PyTorch中创建了相同的模型架构,并将训练过的权重应用于PyTorch模型。现在我的期望是从Tensorflow和PyTorch模型中获得相同的测试精度,但事实并非如此。我得到了不同的结果

所以我的问题是:如果一个模型被训练到某个最优值,那么训练的权重不应该在每次对同一个数据集进行测试时产生相同的结果吗(不管使用的框架是什么)

PyTorch型号:

class Net(nn.Module):

def __init__(self) -> None:
    super(Net, self).__init__()
    self.fc1 = nn.Linear(784, 24)
    self.fc2 = nn.Linear(24, 10)

def forward(self, x: Tensor) -> Tensor:
    x = torch.flatten(x, 1)
    x = F.relu(self.fc1(x))
    x = self.fc2(x)
    return x
def build_model() -> tf.keras.Model:
    # Build model layers
    model = models.Sequential()
    # Flatten Layer
    model.add(layers.Flatten(input_shape=(28,28)))
    # Fully connected layer
    model.add(layers.Dense(24, activation='relu'))
    model.add(layers.Dense(10))
    # compile the model
    model.compile(
        optimizer='sgd',
        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
        metrics=['accuracy']
    )
    # return newly built model
    return model
def get_weights(model):
    # fetch latest weights
    weights = model.get_weights()
    # transpose weights
    t_weights = []
    for w in weights:
        t_weights.append(np.transpose(w))
    # return
    return t_weights
def set_weights(model, weights):
    """Set model weights from a list of NumPy ndarrays."""
    state_dict = OrderedDict(
        {k: torch.Tensor(v) for k, v in zip(model.state_dict().keys(), weights)}
    )
    self.load_state_dict(state_dict, strict=True)
Tensorflow模型:

class Net(nn.Module):

def __init__(self) -> None:
    super(Net, self).__init__()
    self.fc1 = nn.Linear(784, 24)
    self.fc2 = nn.Linear(24, 10)

def forward(self, x: Tensor) -> Tensor:
    x = torch.flatten(x, 1)
    x = F.relu(self.fc1(x))
    x = self.fc2(x)
    return x
def build_model() -> tf.keras.Model:
    # Build model layers
    model = models.Sequential()
    # Flatten Layer
    model.add(layers.Flatten(input_shape=(28,28)))
    # Fully connected layer
    model.add(layers.Dense(24, activation='relu'))
    model.add(layers.Dense(10))
    # compile the model
    model.compile(
        optimizer='sgd',
        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
        metrics=['accuracy']
    )
    # return newly built model
    return model
def get_weights(model):
    # fetch latest weights
    weights = model.get_weights()
    # transpose weights
    t_weights = []
    for w in weights:
        t_weights.append(np.transpose(w))
    # return
    return t_weights
def set_weights(model, weights):
    """Set model weights from a list of NumPy ndarrays."""
    state_dict = OrderedDict(
        {k: torch.Tensor(v) for k, v in zip(model.state_dict().keys(), weights)}
    )
    self.load_state_dict(state_dict, strict=True)
要从Tensorflow模型中提取权重并将其应用于Pytorch模型,我使用以下函数:

提取权重:

class Net(nn.Module):

def __init__(self) -> None:
    super(Net, self).__init__()
    self.fc1 = nn.Linear(784, 24)
    self.fc2 = nn.Linear(24, 10)

def forward(self, x: Tensor) -> Tensor:
    x = torch.flatten(x, 1)
    x = F.relu(self.fc1(x))
    x = self.fc2(x)
    return x
def build_model() -> tf.keras.Model:
    # Build model layers
    model = models.Sequential()
    # Flatten Layer
    model.add(layers.Flatten(input_shape=(28,28)))
    # Fully connected layer
    model.add(layers.Dense(24, activation='relu'))
    model.add(layers.Dense(10))
    # compile the model
    model.compile(
        optimizer='sgd',
        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
        metrics=['accuracy']
    )
    # return newly built model
    return model
def get_weights(model):
    # fetch latest weights
    weights = model.get_weights()
    # transpose weights
    t_weights = []
    for w in weights:
        t_weights.append(np.transpose(w))
    # return
    return t_weights
def set_weights(model, weights):
    """Set model weights from a list of NumPy ndarrays."""
    state_dict = OrderedDict(
        {k: torch.Tensor(v) for k, v in zip(model.state_dict().keys(), weights)}
    )
    self.load_state_dict(state_dict, strict=True)
应用权重:

class Net(nn.Module):

def __init__(self) -> None:
    super(Net, self).__init__()
    self.fc1 = nn.Linear(784, 24)
    self.fc2 = nn.Linear(24, 10)

def forward(self, x: Tensor) -> Tensor:
    x = torch.flatten(x, 1)
    x = F.relu(self.fc1(x))
    x = self.fc2(x)
    return x
def build_model() -> tf.keras.Model:
    # Build model layers
    model = models.Sequential()
    # Flatten Layer
    model.add(layers.Flatten(input_shape=(28,28)))
    # Fully connected layer
    model.add(layers.Dense(24, activation='relu'))
    model.add(layers.Dense(10))
    # compile the model
    model.compile(
        optimizer='sgd',
        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
        metrics=['accuracy']
    )
    # return newly built model
    return model
def get_weights(model):
    # fetch latest weights
    weights = model.get_weights()
    # transpose weights
    t_weights = []
    for w in weights:
        t_weights.append(np.transpose(w))
    # return
    return t_weights
def set_weights(model, weights):
    """Set model weights from a list of NumPy ndarrays."""
    state_dict = OrderedDict(
        {k: torch.Tensor(v) for k, v in zip(model.state_dict().keys(), weights)}
    )
    self.load_state_dict(state_dict, strict=True)

在回答部分为社区提供解决方案。根据评论


如果以相同的方式使用相同的权重,则结果相同 应相同,但浮点舍入误差也应相同 算了。而且,模型是否经过训练也无关紧要。你可以 将模型体系结构视为矩阵乘法链 元素非线性介于两者之间。这个房间有多大 区别?您是否在比较模型输出,我们计算的指标 数据集?作为一项建议,使用中的一些随机值初始化模型 Keras,对单个批次进行正向传递(摘自jdehesa和Taras Sereda)


如果您以相同的方式使用相同的权重,那么是的,结果应该是相同的(保留由于不同实现而产生的微小差异)。模型的架构可能有所不同,但如果没有可复制的示例,就无法判断。抱歉,这只是一个好奇,让我发布实际模型以更清晰。结果应该是相同的,但也应该考虑浮点舍入误差。而且,模型是否经过训练也无关紧要。您可以将模型体系结构视为一个矩阵乘法链,其间存在元素非线性。差别有多大?您是否在比较模型输出和我们在数据集上计算的指标?作为建议,在Keras中使用一些随机值初始化模型,对单个批次进行正向传递。然后使用导出的参数在Pytorch中执行相同的操作。祝你好运@塔拉塞德提出了一个绝妙的建议,我不知道为什么我没有想到要这么做。我试着比较原始输出,它们几乎相同(由于四舍五入,小数点后第7位或第8位的差异较小)。我所观察到的差异在于准确性,我认为我在这两个框架中使用的指标是不同的。不管怎样,我的问题现在已经解决了。非常感谢。