tf.keras的`predict()`函数得到不同的结果

4

我在玩弄tf.keras,并对两个初始化权重相同的Model对象运行了一些predict()方法。

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import LSTM, Masking, Input, Embedding, Dense
from tensorflow.keras.models import Model

tf.enable_eager_execution()
np.random.seed(10)

X = np.asarray([
    [0, 1, 2, 3, 3],
    [0, 0, 1, 1, 1],
    [0, 0, 0, 1, 1],
])

y = [
    0,
    1,
    1
]

seq_len = X.shape[1]

inp = Input(shape=[seq_len])
emb = Embedding(4, 10, name='embedding')(inp)

x = emb
x = LSTM(5, return_sequences=False, name='lstm')(x)
out = Dense(1, activation='sigmoid', name='out')(x)

model = Model(inputs=inp, outputs=out)
model.summary()

preds = model.predict(X)

inp = Input(shape=[seq_len])
emb = Embedding(4, 10, name='embedding', weights=model.get_layer('embedding').get_weights()[0])(inp)

x = emb
x = LSTM(5, return_sequences=False, weights=model.get_layer('lstm').get_weights()[0])(x)
out = Dense(1, activation='sigmoid', weights=model.get_layer('out').get_weights()[0])(x)

model_2 = Model(inputs=inp, outputs=out)
model_2.summary()

preds_2 = model_2.predict(X)

print(preds, preds_2)

我不确定为什么两个预测结果不同。我运行 print 函数时得到了这些结果。你可能会得到不同的结果。
[[0.5027414 ]
 [0.5019673 ]
 [0.50134844]] [[0.5007331]
 [0.5002397]
 [0.4996575]]

我正在尝试了解keras的工作原理,感谢您能提供任何解释。请注意:这里没有涉及学习。我不明白随机性来自何处。

@Justice_Lords 我没有调用任何model.fit()。我只是使用与其他模型相同的权重初始化一个模型,并在“X”上进行预测。 - Hardian Lawi
我不明白为什么这被标记为 https://dev59.com/wVUL5IYBdhLWcg3wOV2- 的重复内容。我没有训练模型或做任何事情,所以我不知道随机性来自哪里。 - Hardian Lawi
4个回答

0
也许仅仅设置NumPy的种子并不足以使操作和权重确定性。 TensorFlow文档建议为了具有确定性权重,您应该运行:
tf.keras.utils.set_random_seed(1)
tf.config.experimental.enable_op_determinism()

https://www.tensorflow.org/api_docs/python/tf/config/experimental/enable_op_determinism#:~:text=配置TensorFlow操作以确定性地运行。&text=启用操作确定性时,TensorFlow操作将以确定性方式运行,这对于调试模型非常有用。

你能否检查一下它是否有帮助?(你的代码似乎是在TF版本1中编写的,因此需要适应才能在我的v2设置上运行)


0
尝试将优化器从adam更改为SGD或其他选项。我注意到使用相同的模型会得到不同的结果,通过更改优化器可以解决问题。此外,请查看这里以修复初始权重。顺便说一句,我不知道为什么和如何在测试时间中使用相同的模型会受到优化器影响。

问题中的代码并没有进行任何训练,因此根本没有使用优化器。第二个模型的初始化也是使用与第一个模型相同的权重。这篇文章并没有真正回答关于结果差异来自何处的问题。在发表答案之前,最好仔细阅读原始帖子、其他答案和评论。 - GZ0

0

问题在于你没有复制所有的权重。我不知道为什么你的调用可以工作,但通过检查未使用 [0] 索引的 get_weights 很容易看出你没有复制。

例如,这些内容没有被复制:

model.get_layer('lstm').get_weights()[1]


array([[ 0.11243069, -0.1028666 ,  0.01080172, -0.07471965,  0.05566487,
        -0.12818974,  0.34882438, -0.17163819, -0.21306667,  0.5386005 ,
        -0.03643916,  0.03835883, -0.31128728,  0.04882491, -0.05503649,
        -0.22660127, -0.4683674 , -0.00415642, -0.29038426, -0.06893865],
       [-0.5117522 ,  0.01057898, -0.23182054,  0.03220385,  0.21614116,
         0.0732751 , -0.30829042,  0.06233712, -0.54017985, -0.1026137 ,
        -0.18011908,  0.15880923, -0.21900705, -0.11910527, -0.03808065,
         0.07623457, -0.13157862, -0.18740109,  0.06135096, -0.21589288],
       [-0.2295578 , -0.12452635, -0.08739456, -0.1880849 ,  0.2220488 ,
        -0.14575425,  0.32249492,  0.05235165, -0.09479579,  0.2496742 ,
         0.10411342, -0.0263749 ,  0.33186644, -0.1838699 ,  0.28964192,
        -0.2414586 ,  0.41612682,  0.13791762,  0.13942356, -0.36176005],
       [-0.14428475, -0.02090888,  0.27968913,  0.09452424,  0.1291543 ,
        -0.43372717, -0.11366601,  0.37842247,  0.3320751 ,  0.21959782,
        -0.4242381 ,  0.02412989, -0.24809352,  0.2508208 , -0.06223384,
         0.08648364,  0.17311276, -0.05988384,  0.02276517, -0.1473657 ],
       [ 0.28600952, -0.37206012,  0.21376705, -0.16566195,  0.0833357 ,
        -0.00887177,  0.01394618,  0.5345957 , -0.25116244, -0.17159337,
         0.096329  , -0.32286254,  0.02044407, -0.1393016 , -0.0767666 ,
         0.1505355 , -0.28456056,  0.16909163,  0.16806729, -0.14622769]],
      dtype=float32)

而且,如果您在模型2中命名了LSTM层,您会发现权重的部分并不相等。

model_2.get_layer("lstm").get_weights()[1] - model.get_layer("lstm").get_weights()[1]

-3
关于机器学习的事情是它并不总是以相同的方式进行学习。它涉及大量的概率,因此在更大的范围内,结果往往会趋向于一个值,但是单独的运行可能会产生不同的结果。 更多信息请点击这里 “许多使用相同输入数据的运行产生不同输出是完全正常的。这主要是由于这些机器学习技术(例如:ANN、决策树构建算法等)的内部随机性所致。”
- Nabil Belgasmi, Université de la Manouba
“没有特定的方法或技术。性能的结果和评估取决于几个因素:数据类型、感应函数参数、训练集(监督)、等等。重要的是使用度量标准如召回率、精确度、F_measure、ROC曲线或其他图形方法来比较结果。”
- Jésus Antonio Motta Laval University

编辑 predict() 函数接受一个或多个数据实例的数组。

下面的示例演示了如何对具有未知预期结果的多个数据实例进行回归预测。

# example of making predictions for a regression problem
from keras.models import Sequential
from keras.layers import Dense
from sklearn.datasets import make_regression
from sklearn.preprocessing import MinMaxScaler
# generate regression dataset
X, y = make_regression(n_samples=100, n_features=2, noise=0.1, random_state=1)
scalarX, scalarY = MinMaxScaler(), MinMaxScaler()
scalarX.fit(X)
scalarY.fit(y.reshape(100,1))
X = scalarX.transform(X)
y = scalarY.transform(y.reshape(100,1))
# define and fit the final model
model = Sequential()
model.add(Dense(4, input_dim=2, activation='relu'))
model.add(Dense(4, activation='relu'))
model.add(Dense(1, activation='linear'))
model.compile(loss='mse', optimizer='adam')
model.fit(X, y, epochs=1000, verbose=0)
# new instances where we do not know the answer
Xnew, a = make_regression(n_samples=3, n_features=2, noise=0.1, random_state=1)
Xnew = scalarX.transform(Xnew)
# make a prediction
ynew = model.predict(Xnew)
# show the inputs and predicted outputs
for i in range(len(Xnew)):
    print("X=%s, Predicted=%s" % (Xnew[i], ynew[i]))

运行示例会进行多次预测,然后将输入和预测并排打印以供查看。

X=[0.29466096 0.30317302], Predicted=[0.17097184]
X=[0.39445118 0.79390858], Predicted=[0.7475489]
X=[0.02884127 0.6208843 ], Predicted=[0.43370453]

来源

免责声明: predict() 函数本身略带随机性(概率性)


你期望在一个真正的答案中看到什么?楼主要求解释。 - Jessica Chambers
@JessicaChambers 我没有重新训练任何模型。我只是简单地使用另一个模型的权重初始化了一些模型,并在相同的 X 上进行预测。这里没有涉及到任何学习。 - Hardian Lawi
2
@HardianLawi predict() 函数本身略带随机性(概率性),是一种机器学习形式。请查看此页面上的第3节“回归预测” https://machinelearningmastery.com/how-to-make-classification-and-regression-predictions-for-deep-learning-models-in-keras/ - Jessica Chambers
@JessicaChambers 为什么 predict() 函数是随机的?另外,你没有理解我的观点。我没有训练任何模型。 - Hardian Lawi
1
@JessicaChambers,如果您在主体答案部分添加注释“predict()函数本身略微随机...”,我认为您的回答会更好。 - user11563547
3
我认为你将“训练”与“预测”混淆了。你的来源提到了在(随机)训练阶段之前进行预测。正如原始贴子指出的那样,权重是固定的,所以没有训练步骤,或者任何机器学习的步骤,因此结果每次应该都是相同的。 - c z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接