top-5精度是否可能低于top-1精度?

时间:2020-07-08 10:12:44

标签: python keras

在我的训练结果中: enter image description here

我的代码:

import keras
from keras import datasets
from keras import layers
from keras import models
print(f'keras版本={keras.__version__}')
#載入 cifar10 資料庫的訓練資料,並自動分為『訓練組』及『測試組』
(X_train, y_train),(X_test, y_test)= datasets.cifar10.load_data()
#建立FNN model
model = models.Sequential()
#建立input層
#此例若沒加Flatten Layer則會出錯(dense_數字,此數字後面會變動,其餘都一樣):
#ValueError: Error when checking target: expected dense_30 to have 3 dimensions, but got array with shape (60000, 1)
model.add(layers.Flatten())
#建立隱藏層(此例中此隱藏層只有1個神經元)
#可以寫得較完整:model.add(layers.Dense(input_dim=28*28,units=2))
#units的舊式寫法為output_dim:model.add(layers.Dense(input_dim=28*28,output_dim=2))
model.add(layers.Dense(units=1))
#建立輸出層(輸出神經元至少>=10)
model.add(layers.Dense(units=10))
import functools
#若將k=5改成k=3就會變成計算Top-3
top5_acc = functools.partial(keras.metrics.top_k_categorical_accuracy, k=5)
#此名稱可自訂,當training時顯示用的
top5_acc.__name__ = 'top5_acc'
# 最佳化設定
#若loss設定為categorical_crossentropy則會出錯:
#ValueError: Error when checking target: expected dense_2 to have shape (10,) but got array with shape (1,)
model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['accuracy',top5_acc])
# 開始進行training
model.fit(
    x=X_train,
    y=y_train,
    epochs=1,
    verbose=1,
    validation_split=0.1
)
#若沒有呼叫
#input_shape = [28,28,1]
#build(input_shape)
#的話,唯有在fit()之後才能呼叫summary()
#否則會出錯:
#This model has not yet been built. Build the model first by calling build() or calling fit() with some data.
#Or specify input_shape or batch_input_shape in the first layer for automatic build.
#model.build(input_shape)
model.summary()
# 開始進行testing
test_loss,top_1_accuracy, top_5_accuracy = model.evaluate(X_test, y_test)
print(f'test_loss={test_loss}')
print(f'top_1_accuracy={top_1_accuracy}')
print(f'top_5_accuracy={top_5_accuracy}')

是否存在设置错误或概念错误?

谢谢〜

====================================

将精度更改为categorical_accuracy后:

import keras
from keras import datasets
from keras import layers
from keras import models
print(f'keras版本={keras.__version__}')
#載入 cifar10 資料庫的訓練資料,並自動分為『訓練組』及『測試組』
(X_train, y_train),(X_test, y_test)= datasets.cifar10.load_data()
#建立FNN model
model = models.Sequential()
#建立input層
#此例若沒加Flatten Layer則會出錯(dense_數字,此數字後面會變動,其餘都一樣):
#ValueError: Error when checking target: expected dense_30 to have 3 dimensions, but got array with shape (60000, 1)
model.add(layers.Flatten())
#建立隱藏層(此例中此隱藏層只有1個神經元)
#可以寫得較完整:model.add(layers.Dense(input_dim=28*28,units=2))
#units的舊式寫法為output_dim:model.add(layers.Dense(input_dim=28*28,output_dim=2))
model.add(layers.Dense(units=1))
#建立輸出層(輸出神經元至少>=10)
model.add(layers.Dense(units=10))
import functools
#若將k=5改成k=3就會變成計算Top-3
top5_acc = functools.partial(keras.metrics.top_k_categorical_accuracy, k=5)
#此名稱可自訂,當training時顯示用的
top5_acc.__name__ = 'top5_acc'
# 最佳化設定
#若loss設定為categorical_crossentropy則會出錯:
#ValueError: Error when checking target: expected dense_2 to have shape (10,) but got array with shape (1,)
model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['categorical_accuracy',top5_acc])
# 開始進行training
model.fit(
    x=X_train,
    y=y_train,
    epochs=1,
    verbose=1,
    validation_split=0.1
)
#若沒有呼叫
#input_shape = [28,28,1]
#build(input_shape)
#的話,唯有在fit()之後才能呼叫summary()
#否則會出錯:
#This model has not yet been built. Build the model first by calling build() or calling fit() with some data.
#Or specify input_shape or batch_input_shape in the first layer for automatic build.
#model.build(input_shape)
model.summary()
# 開始進行testing
test_loss,top_1_accuracy, top_5_accuracy = model.evaluate(X_test, y_test)
print(f'test_loss={test_loss}')
print(f'top_1_accuracy={top_1_accuracy}')
print(f'top_5_accuracy={top_5_accuracy}')

我知道了

enter image description here

===我添加softmax ===

import keras
from keras import datasets
from keras import layers
from keras import models
print(f'keras版本={keras.__version__}')
#載入 cifar10 資料庫的訓練資料,並自動分為『訓練組』及『測試組』
(X_train, y_train),(X_test, y_test)= datasets.cifar10.load_data()
#建立FNN model
model = models.Sequential()
#建立input層
#此例若沒加Flatten Layer則會出錯(dense_數字,此數字後面會變動,其餘都一樣):
#ValueError: Error when checking target: expected dense_30 to have 3 dimensions, but got array with shape (60000, 1)
model.add(layers.Flatten())
#建立隱藏層(此例中此隱藏層只有1個神經元)
#可以寫得較完整:model.add(layers.Dense(input_dim=28*28,units=2))
#units的舊式寫法為output_dim:model.add(layers.Dense(input_dim=28*28,output_dim=2))
model.add(layers.Dense(units=1))
#建立輸出層(輸出神經元至少>=10)
model.add(layers.Dense(units=10,activation='softmax'))
import functools
#若將k=5改成k=3就會變成計算Top-3
top5_acc = functools.partial(keras.metrics.top_k_categorical_accuracy, k=5)
#此名稱可自訂,當training時顯示用的
top5_acc.__name__ = 'top5_acc'
# 最佳化設定
#若loss設定為categorical_crossentropy則會出錯:
#ValueError: Error when checking target: expected dense_2 to have shape (10,) but got array with shape (1,)
model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['categorical_accuracy',top5_acc])
# 開始進行training
model.fit(
    x=X_train,
    y=y_train,
    epochs=1,
    verbose=1,
    validation_split=0.1
)
#若沒有呼叫
#input_shape = [28,28,1]
#build(input_shape)
#的話,唯有在fit()之後才能呼叫summary()
#否則會出錯:
#This model has not yet been built. Build the model first by calling build() or calling fit() with some data.
#Or specify input_shape or batch_input_shape in the first layer for automatic build.
#model.build(input_shape)
model.summary()
# 開始進行testing
test_loss,top_1_accuracy, top_5_accuracy = model.evaluate(X_test, y_test)
print(f'test_loss={test_loss}')
print(f'top_1_accuracy={top_1_accuracy}')
print(f'top_5_accuracy={top_5_accuracy}')

我得到了:

enter image description here

================================================ ==

感谢@Thomas Schillaci的建议, 我发现一个没有任何错误:

import keras
from keras import datasets
from keras import layers
from keras import models
print(f'keras版本={keras.__version__}')
#載入 cifar10 資料庫的訓練資料,並自動分為『訓練組』及『測試組』
(X_train, y_train),(X_test, y_test)= datasets.cifar10.load_data()
#建立FNN model
model = models.Sequential()
#建立input層
#此例若沒加Flatten Layer則會出錯(dense_數字,此數字後面會變動,其餘都一樣):
#ValueError: Error when checking target: expected dense_30 to have 3 dimensions, but got array with shape (60000, 1)
model.add(layers.Flatten())
#建立隱藏層(此例中此隱藏層只有1個神經元)
#可以寫得較完整:model.add(layers.Dense(input_dim=28*28,units=2))
#units的舊式寫法為output_dim:model.add(layers.Dense(input_dim=28*28,output_dim=2))
model.add(layers.Dense(units=1))
#建立輸出層(輸出神經元至少>=10)
model.add(layers.Dense(units=10,activation='softmax'))
import functools

#底下寫法會怪怪的,如:top1=99.64、top-5=0.0
#若將k=5改成k=3就會變成計算Top-3
#top5_acc = functools.partial(keras.metrics.top_k_categorical_accuracy, k=5)
#此名稱可自訂,當training時顯示用的
#top5_acc.__name__ = 'top5_acc'
# 最佳化設定
#若loss設定為categorical_crossentropy則會出錯:
#ValueError: Error when checking target: expected dense_2 to have shape (10,) but got array with shape (1,)
#model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['categorical_accuracy',top5_acc])

#底下寫法會出錯:ValueError: '<lambda>' is not a valid scope name
#from keras import metrics
#top3 = lambda x,y: metrics.top_k_categorical_accuracy(x,y,3)
#top5 = lambda x,y: metrics.top_k_categorical_accuracy(x,y,5)
#model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['accuracy',top3,top5])

#底下寫法會出錯:ValueError: None values not supported.
#def top3(x,y):
#    metrics.top_k_categorical_accuracy(x,y,3)
#def top5(x,y):
#    metrics.top_k_categorical_accuracy(x,y,5)
#model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['accuracy',top3,top5])

#底下寫法training時正確:accuracy: 0.1371 - top_k_categorical_accuracy: 0.4191 - acc_top3: 0.2147
#但testing時出錯:
# top_1_accuracy=0.15530000627040863
# top_3_accuracy=0.0
# top_5_accuracy=0.0
#而且會顯示:top_k_categorical_accuracy而非顯示top-5
#45000/45000 [==============================] - 2s 52us/step - loss: 7.9220
#- accuracy: 0.1136 - top_k_categorical_accuracy: 0.4338 - acc_top3: 0.3794 - val_loss: 2.2809
# - val_accuracy: 0.1470 - val_top_k_categorical_accuracy: 0.2550 - val_acc_top3: 0.2412
# def acc_top3(y_true, y_pred):
    # return metrics.top_k_categorical_accuracy(y_true, y_pred, k=3)
# model.compile(loss='sparse_categorical_crossentropy',
              # optimizer='adam',
              # metrics=['accuracy', metrics.top_k_categorical_accuracy, acc_top3])

#底下寫法training時正確:accuracy: 0.1332 - top5_acc: 0.5029 - acc_top3: 0.3971
#但testing時出錯:
# top_1_accuracy=0.16220000386238098
# top_3_accuracy=0.08720000088214874
# top_5_accuracy=0.3935000002384186
#top5_acc = functools.partial(keras.metrics.top_k_categorical_accuracy, k=5)
#此名稱可自訂,當training時顯示用的
# top5_acc.__name__ = 'top5_acc'
# def acc_top3(y_true, y_pred):
   # return metrics.top_k_categorical_accuracy(y_true, y_pred, k=3)
# model.compile(loss='sparse_categorical_crossentropy',
             # optimizer='adam',
             # metrics=['accuracy', top5_acc, acc_top3])

#底下寫法training時正確:acc: 0.1314 - acc_top2: 0.4392 - acc_top3: 0.4797 - acc_top4: 0.5172 - acc_top5: 0.5492
#但testing時出錯:
# top_1_accuracy=0.13410000503063202
# top_2_accuracy=0.03440000116825104
# top_3_accuracy=0.034699998795986176
# top_4_accuracy=0.03669999912381172
# top_5_accuracy=0.042399998754262924
# from keras.metrics import top_k_categorical_accuracy
# def acc_top2(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=2)
    
# def acc_top3(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=3)

# def acc_top4(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=4)

# def acc_top5(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=5)
# model.compile(loss='sparse_categorical_crossentropy',
              # optimizer='adam',
              # metrics=['acc', acc_top2, acc_top3, acc_top4, acc_top5])

#底下寫法training時正確:acc: 0.1314 - acc_top2: 0.4392 - acc_top3: 0.4797 - acc_top4: 0.5172 - acc_top5: 0.5492
#但testing時出錯:
# top_1_accuracy=0.15760000050067902
# top_2_accuracy=0.0
# top_3_accuracy=0.125900000333786
# top_4_accuracy=0.48910000920295715
# top_5_accuracy=0.6032000184059143
# from keras.metrics import top_k_categorical_accuracy
# def acc_top2(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=2)
    
# def acc_top3(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=3)

# def acc_top4(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=4)

# def acc_top5(y_true, y_pred):
    # return top_k_categorical_accuracy(y_true, y_pred, k=5)
# model.compile(loss='sparse_categorical_crossentropy',
              # optimizer='adam',
              # metrics=['accuracy', acc_top2, acc_top3, acc_top4, acc_top5])
             
from keras.metrics import top_k_categorical_accuracy
def acc_top2(y_true, y_pred):
    return top_k_categorical_accuracy(y_true, y_pred, k=2)
    
def acc_top3(y_true, y_pred):
    return top_k_categorical_accuracy(y_true, y_pred, k=3)

def acc_top4(y_true, y_pred):
    return top_k_categorical_accuracy(y_true, y_pred, k=4)

def acc_top5(y_true, y_pred):
    return top_k_categorical_accuracy(y_true, y_pred, k=5)
model.compile(loss='sparse_categorical_crossentropy',
              optimizer='adam',
              metrics=['categorical_accuracy', acc_top2, acc_top3, acc_top4, acc_top5])
#底下看似正確,但卻有一次例外,其他次全對,但無法reproduce該次錯誤
# model.compile(loss='sparse_categorical_crossentropy',
              # optimizer='adam',
              # metrics=['accuracy', metrics.top_k_categorical_accuracy])
# 開始進行training
model.fit(
    x=X_train,
    y=y_train,
    epochs=1,
    verbose=1,
    validation_split=0.1
)
#若沒有呼叫
#input_shape = [28,28,1]
#build(input_shape)
#的話,唯有在fit()之後才能呼叫summary()
#否則會出錯:
#This model has not yet been built. Build the model first by calling build() or calling fit() with some data.
#Or specify input_shape or batch_input_shape in the first layer for automatic build.
#model.build(input_shape)
model.summary()
# 開始進行testing
#test_loss,top_1_accuracy, top_5_accuracy, top_3_accuracy = model.evaluate(X_test, y_test)
#test_loss,top_1_accuracy, top_5_accuracy = model.evaluate(X_test, y_test)
test_loss,top_1_accuracy, top_2_accuracy, top_3_accuracy, top_4_accuracy, top_5_accuracy = model.evaluate(X_test, y_test)
print(model.metrics_names)
print(f'test_loss={test_loss}')
print(f'top_1_accuracy={top_1_accuracy}')
print(f'top_2_accuracy={top_2_accuracy}')
print(f'top_3_accuracy={top_3_accuracy}')
print(f'top_4_accuracy={top_4_accuracy}')
print(f'top_5_accuracy={top_5_accuracy}')

结果很好:

enter image description here

1 个答案:

答案 0 :(得分:1)

您使用的是前1位的准确性指标和前5位的分类准确性指标。将第一个切换为'categorical_accuracy'应该可以解决问题