Keras预报()比评估()返回更好的准确性

DDD*_*DDD 8 python numpy machine-learning keras tensorflow

我使用Keras建立了一个模型,然后在3条记录的数据集上对其进行了训练,最后我对两个函数使用了相同的测试集(分别具有100条记录和考虑到两个数据集的大小,它没有关于训练集的任何记录,尽管它可能是相关的。数据集由5个文件组成,其中4个文件分别代表一个不同的温度传感器,每分钟收集60个测量值(每行包含60个测量值),最后一个文件包含我要预测的类标签(特别是, 3类:3、20或100)。

这是我正在使用的模型:

n_sensors, t_periods = 4, 60

model = Sequential()

model.add(Conv1D(100, 6, activation='relu', input_shape=(t_periods, n_sensors)))

model.add(Conv1D(100, 6, activation='relu'))

model.add(MaxPooling1D(3))

model.add(Conv1D(160, 6, activation='relu'))

model.add(Conv1D(160, 6, activation='relu'))

model.add(GlobalAveragePooling1D())

model.add(Dropout(0.5))

model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
Run Code Online (Sandbox Code Playgroud)

我训练的: self.model.fit(X_train, y_train, batch_size=3, epochs=5, verbose=1)

然后我使用评估: self.model.evaluate(x_test, y_test, verbose=1)

并预测:

predictions = self.model.predict(data)
result = np.where(predictions[0] == np.amax(predictions[0]))
if result[0][0] == 0:
    return '3'
elif result[0][0] == 1:
    return '20'
else:
    return '100'
Run Code Online (Sandbox Code Playgroud)

对于每个预测的类,我将使用实际的标签来对付它,然后计算正确的猜测/总计示例,这些示例应等效于评估()函数的准确性。这是代码:

correct = 0
for profile in self.profile_file: #profile_file is an opened file
    ts1 = self.ts1_file.readline()
    ts2 = self.ts2_file.readline()
    ts3 = self.ts3_file.readline()
    ts4 = self.ts4_file.readline()
    data = ts1, ts2, ts3, ts4
    test_data = self.dl.transform(data) # see the last block of code I posted
    prediction = self.model.predict(test_data)
    if prediction == label:
       correct += 1
acc = correct / 100 # 100 is the number of total examples
Run Code Online (Sandbox Code Playgroud)

从此函数获取提供给评价()的数据:

label = pd.read_csv(os.path.join(self.testDir, 'profile.txt'), sep='\t', header=None)
label = np_utils.to_categorical(label[0].factorize()[0])
data = [os.path.join(self.testDir,'TS2.txt'),os.path.join(self.testDir, 'TS1.txt'),os.path.join(self.testDir,'TS3.txt'),os.path.join(self.testDir, 'TS4.txt')]
df = pd.DataFrame()
for txt in data:
    read_df = pd.read_csv(txt, sep='\t', header=None)
    df = df.append(read_df)
df = df.apply(self.__predict_scale)
df = df.sort_index().values.reshape(-1,4,60).transpose(0,2,1)
return df, label
Run Code Online (Sandbox Code Playgroud)

馈送给predict()的数据是从另一数据中获取的:

df = pd.DataFrame()
for txt in data: # data 
    read_df = pd.read_csv(StringIO(txt), sep='\t', header=None)
    df = df.append(read_df)
df = df.apply(self.__predict_scale)
df = df.sort_index().values.reshape(-1,4,60).transpose(0,2,1)
return df
Run Code Online (Sandbox Code Playgroud)

由Evaluate()和predict()产生的精度始终是不同的:特别是,我注意到的最大差异是,Evaluate()的精度为78%,而predict()的精度为95%。这两个函数之间的唯一区别是,我使一次一次在一个示例上运行了predict(),而evaluate()一次处理了整个数据集,但不会有任何区别。怎么会这样?

更新1:似乎问题出在我如何准备数据。在使用predict()的情况下,我使用我发布的最后一个代码块一次只转换每个文件中的一行,而在馈送evaluate()时,我使用报告的其他函数来转换整个文件。为什么要与众不同?在我看来,我正在应用完全相同的转换,唯一的区别是转换的行数。

spa*_*les 5

这个问题已经在这里得到回答

当您评估模型时会发生什么,因为您的损失函数是 categorical_crossentropy,所以metrics=['accuracy']会计算 categorical_accuracy。

但预测的默认设置为binary_accuracy。

因此,本质上,您是通过评估来计算分类准确性,并通过预测来计算二进制准确性。这就是它们如此不同的原因。

categorical_accuracy 和 binary_accuracy 之间的区别在于,categorical_accuracy 检查所有输出是否与 y_test 匹配,binary_accuracy 检查每个输出是否与 y_test 匹配。

示例(单行):

prediction = [0,0,1,1,0]
y_test = [0,0,0,1,0]

categorical_accuracy = 0% 
Run Code Online (Sandbox Code Playgroud)

由于 1 个输出与 categorical_accuracy 不匹配,因此为 0

binary_accuracy = 80% 
Run Code Online (Sandbox Code Playgroud)

即使 1 个输出与其余 80% 的输出不匹配,但仍匹配,因此准确度为 80%