【问题标题】:get same output when making prediction进行预测时获得相同的输出
【发布时间】:2019-06-04 20:47:36
【问题描述】:

我是机器学习新手。我正在尝试制作一个包含数字的图像分类的基本示例。我创建了自己的数据集,但准确率很差(11%)。我有 246 个训练项目和 62 个测试项目。 这是我的代码:

#TRAINING

def load_data(input_path, img_height, img_width):
  data = []
  labels = []
  for imagePath in os.listdir(input_path):  
    labels_path = os.path.join(input_path, imagePath)
    if os.path.isdir(labels_path): 
      for img_path in os.listdir(labels_path):
        labels.append(imagePath)
        img_full_path = os.path.join(labels_path, img_path)
        img = image.load_img(img_full_path, target_size=(img_height, img_width)) 
        img = image.img_to_array(img)
        data.append(img)
  return data, labels



  train_data = []
  train_labels = []
  test_data = []
  test_labels = []
  train_data, train_labels = load_data(train_path, 28, 28)
  test_data, test_labels = load_data(test_path, 28, 28)


  train_data = np.array(train_data)
  train_data = train_data / 255.0
  train_data = tf.reshape(train_data, train_data.shape[:3])
  train_labels = np.array(train_labels)
  train_labels = np.asfarray(train_labels,float)


  test_data = np.array(test_data) 
  test_data = tf.reshape(test_data, test_data.shape[:3])
  test_data = test_data / 255.0
  test_labels = np.array(test_labels)


 model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(512, activation=tf.nn.relu),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax)
  ])


  model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])


  model.fit(train_data, train_labels, batch_size=10, epochs=5, steps_per_epoch=246)

  test_loss, test_acc = model.evaluate(test_data, test_labels, steps=1)
  print('Test accuracy:', test_acc)

#CLASSIFICATION

def classify(input_path):
    if os.path.isdir(input_path):
        images = []
        for file_path in os.listdir(input_path):
            full_path = os.path.join(input_path, file_path)
            img_tensor = preprocess_images(full_path, 28, 28, "L")
            images.append(img_tensor)
        images = np.array(images)
        images = tf.reshape(images,(images.shape[0],images.shape[2],images.shape[3]))
        predictions = model.predict(images, steps = 1)


        for i in range(len(predictions)):
            print("Image", i , "is", np.argmax(predictions[i]))

def preprocess_images(image_path, img_height, img_width, mode):
    img = image.load_img(image_path, target_size=(img_height, img_width))
    #convert 3-channel image to 1-channel
    img = img.convert(mode)
    img_tensor = image.img_to_array(img) 
    img_tensor = np.expand_dims(img_tensor, axis=0)   
    img_tensor /= 255.0
    img_tensor = tf.reshape(img_tensor, img_tensor.shape[:3])
    return tf.keras.backend.eval(img_tensor)

当我进行预测时,我总是得到“图像为 5”的结果。所以,我有 2 个问题: - 我怎样才能得到其他类 [0-9] 作为输出? - 我可以通过增加数据的数量来获得更好的准确性吗?

谢谢。

【问题讨论】:

    标签: python tensorflow machine-learning


    【解决方案1】:

    TLDR;

    你的 load_data() 函数是罪魁祸首 - 你需要将数据集的标签作为整数而不是字符串文件路径返回

    更全面的解释:

    我可以通过增加数据的数量来获得更好的准确性吗?

    一般来说,是的。

    您的模型本质上没有任何问题。我显然无权访问您创建的数据集,但我可以在 MNIST 数据集(您的数据集可能试图镜像)上对其进行测试:

    (train_data, train_labels),(test_data, test_labels) = tf.keras.datasets.mnist.load_data()
    
    
    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(512, activation=tf.nn.relu),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10, activation=tf.nn.softmax)
      ])
    
    
    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
    
    
    model.fit(train_data, train_labels, batch_size=10, epochs=5)
    
    test_loss, test_acc = model.evaluate(test_data, test_labels)
    print('Test accuracy:', test_acc)
    

    这样做后,我们可以训练到大约 93% 的准确率:

    Test accuracy: 0.9275

    然后您的推理代码也可以在测试数据上按预期工作:

    predictions = model.predict(test_data)
    
    for i in range(len(predictions)):
        print("Image", i , "is", np.argmax(predictions[i]))
    

    给出输出,你会期望:

    Image 0 is 7
    Image 1 is 2
    Image 2 is 1
    Image 3 is 0
    Image 4 is 4
    ...
    

    所以我们知道模型可以工作。那么与 MNIST (60000) 相比,性能差异是否仅仅取决于数据集的大小 (246)?

    这很容易测试 - 我们可以从 MNIST 数据中获取类似大小的切片并重复练习:

    train_data = train_data[:246]
    train_labels = train_labels[:246]
    
    test_data = test_data[:62]
    test_labels = test_labels[:62]
    

    所以这次我看到准确度显着降低(这次降低了约 66%),但我可以将模型训练到比您看到的更小得多的子集的准确度。

    因此问题必须与您的数据预处理(或数据集本身)有关。

    其实看你load_data()函数,我可以看出问题出在你生成的标签上。您的labels 只是出现在图像路径中?你有这个:

    # --snip--
    
    for img_path in os.listdir(labels_path):
      labels.append(imagePath) ## <-- this does not look right!
    
    # --snip--
    

    而您需要使用图像所属类别的整数值填充 labels(对于 mnist 数字,这是 0 到 9 之间的整数)

    【讨论】:

    • 非常感谢@Stewart_R 的帮助。问题实际上在于您建议的数据预处理。我还修改了 int 中的标签,它可以工作!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 2017-11-07
    • 1970-01-01
    • 2021-01-25
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多