Низкая точность данных mnist csv в тензорном потоке

Я пытаюсь использовать mnist для начинающих, используя данные csv. Я получил данные csv из здесь и сделал каждую метку горячим вектором. Каждая строка имеет 794 размера (colum1~10 как метка и 11~794 как пиксели). Вот код, который я написал, что приводит к ужасной точности.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys

import tensorflow as tf
import numpy      as np

FLAGS = None

def main(_):
  # Import data
  def csv_to_numpy_array(filepath, delimiter):
      return np.genfromtxt(filepath,delimiter=delimiter, dtype=None)

  def import_data():
      print("loading training data")
      traindata = csv_to_numpy_array("data/mnist_train_onehot.csv",delimiter=",")
      [trainY, trainX] = np.hsplit(traindata,[10]);
      print("loading test data")
      [testY, testX] = np.hsplit(testdata,[10]);
      return trainX, trainY, testX, testY

  x_train, y_train, x_test, y_test = import_data()

  numX = x_train.shape[1] #784
  numY = y_train.shape[1] #10

  # Prepare the placeholder 
  x = tf.placeholder(tf.float32, [None, numX]) #input box
  y_ = tf.placeholder(tf.float32, [None, numY]) #output box

  #define weight and biases
  w = tf.Variable(tf.zeros([numX,numY]))
  b = tf.Variable(tf.zeros([numY]))

  #create the model
  def model(X, w, b):
      pyx = tf.nn.softmax(tf.matmul(X, w) + b)
      return pyx

  y = model(x, w, b)

  #cost function 
  loss = -tf.reduce_sum(y_*tf.log(y))
  # the loss and acc
  cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y),reduction_indices=[1]))
  train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
  init = tf.initialize_all_variables()
  correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

  sess = tf.InteractiveSession()
  tf.global_variables_initializer().run()

  # Train
  for i in range(1000):
      ind = np.random.choice(100,100)
      x_train_batch = x_train[ind]
      y_train_batch = y_train[ind]
        #run optimization op (backprop) and cost op (to get loss value)
      _,c = sess.run([train_step, loss], feed_dict={x: x_train_batch, y_: y_train_batch})
      if i % 50 == 0:
          train_acc = accuracy.eval({x: x_train_batch, y_: y_train_batch})
          print('step: %d, acc: %6.3f' % (i, train_acc) )

  # Test trained model
  print(sess.run(accuracy, feed_dict={x: x_test,
                                      y_: y_test}))

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--data_dir', type=str, default='/tmp/tensorflow/mnist/input_data',
                      help='Directory for storing input data')
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

Точность составляет 0,098 pt. Может ли кто-нибудь попробовать этот код и сказать мне, что не так в этом коде? Заранее большое спасибо.


person Ted    schedule 25.04.2017    source источник
comment
Попробуйте заменить w = tf.Variable(tf.zeros([numX,numY])) на tf.Variable(tf.random_normal([numX, numY])). Вы должны попытаться инициализировать свои веса случайным образом. Если все они равны нулю, градиентный спуск может застрять в исходной позиции. Это также может быть полезно: youtube.com/watch?v=eBbEDRsCmv4.   -  person niczky12    schedule 25.04.2017


Ответы (2)


Вот ваш код с необходимыми изменениями. В частности, вы можете использовать tf.nn.softmax_cross_entropy_with_logits, чтобы выполнить тяжелую работу по вычислению перекрестной энтропии за вас. Другое улучшение заключается в использовании loss = tf.reduce_mean... вместо loss = tf.reduce_sum...*. Таким образом, ваша тренировочная коррекция будет представлять собой среднее значение всех допущенных ошибок, а не сумму. Вы получите дикие и неконтролируемые тренировочные колебания, если будете использовать сумму, и вам придется компенсировать это, используя очень маленький коэффициент градиентного спуска. Если вы обнаружите, что вам нужно использовать что-то в градиентном спуске выше 1 или ниже 0,1, вы, вероятно, могли бы решить проблему, используя reduce_mean для потерь.

Вот ваш код.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys

import tensorflow as tf
import numpy      as np

FLAGS = None

def main(_):
  # Import data
  def csv_to_numpy_array(filepath, delimiter):
      return np.genfromtxt(filepath,delimiter=delimiter, dtype=None)

  def import_data():
      print("loading training data")
      traindata = csv_to_numpy_array("data/mnist_train_onehot.csv",delimiter=",")
      [trainY, trainX] = np.hsplit(traindata,[10]);
      print("loading test data")
      [testY, testX] = np.hsplit(testdata,[10]);
      return trainX, trainY, testX, testY

  x_train, y_train, x_test, y_test = import_data()

  numX = x_train.shape[1] #784
  numY = y_train.shape[1] #10

  # Prepare the placeholder 
  x = tf.placeholder(tf.float32, [None, numX]) #input box
  y_ = tf.placeholder(tf.float32, [None, numY]) #output box

  #define weight and biases
  w = tf.Variable(tf.zeros([numX,numY]))
  b = tf.Variable(tf.zeros([numY]))

  y = tf.matmul(x, w) + b

  # unused for this model
  keep_prob = tf.placeholder(tf.float32)

  loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y, labels=y_))
  train = tf.train.GradientDescentOptimizer(0.5).minimize(loss)

  # Test trained model
  correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
  percent_correct = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

  init = tf.initialize_all_variables()

  sess = tf.InteractiveSession()
  tf.global_variables_initializer().run()

  # Train
  for i in range(1000):
      ind = np.random.choice(x_train.shape[0],100)
      x_train_batch = x_train[ind]
      y_train_batch = y_train[ind]
        #run optimization op (backprop) and cost op (to get loss value)
      _,c = sess.run([train_step, loss], feed_dict={x: x_train_batch, y_: y_train_batch})
      if i % 50 == 0:
          train_acc = percent_correct.eval({x: x_train_batch, y_: y_train_batch})
          print('step: %d, acc: %6.3f' % (i, train_acc) )

  # Test trained model
  print(sess.run(percent_correct, feed_dict={x: x_test,
                                      y_: y_test}))

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--data_dir', type=str, default='/tmp/tensorflow/mnist/input_data',
                      help='Directory for storing input data')
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

Вот ссылка на несколько различных архитектур тензорного потока mnist https://github.com/panchishin/learn-to-tensorflow/blob/master/examples/mnist_model_comparison.py все в одном скрипте

person Anton Codes    schedule 25.04.2017
comment
Спасибо за быстрый ответ. Я изменил функцию потерь, как вы упомянули, а также изменил инициализацию веса и смещения. Но точность все равно низкая (0,53). Я тоже обращусь по ссылке. - person Ted; 26.04.2017
comment
Глядя на строку ind = np.random.choice(100,100), я вижу, что вы используете только первые 100 элементов для обучения, но вы хотите использовать все элементы обучения для обучения. Попробуйте использовать ind = np.random.choice(x_train.shape[0],100) - person Anton Codes; 27.04.2017
comment
Большое спасибо. Теперь я получил правдоподобный результат (0,89 балла) благодаря вашей помощи. Я понимаю, что в данном случае используется случайный выбор random.choice(#alldata, #batchsize). Я так рада, что ты мне помог. Еще раз спасибо. - person Ted; 28.04.2017
comment
Эй, Тед, вы используете только 1 полносвязный слой, поэтому результат 0,89 на самом деле хороший. Если вы добавите один или два слоя свертки 3x3, вы увидите огромное улучшение. Перейдите по этой ссылке, чтобы узнать о нескольких архитектурах mnist и сравнить их производительность. github.com/panchishin/learn-to-tensorflow/ blob/master/examples/ Ваш полностью подключенный слой заставляет NN изучать связь каждого пикселя с ответом. Добавив один слой свертки 3x3, вы вместо этого рассчитаете корреляцию функций (таких как кривые и оттенки) с конечным результатом. - person Anton Codes; 01.05.2017
comment
@Ted, если это улучшило ваш код, отметьте это как правильный ответ. - person Anton Codes; 01.05.2017
comment
где вы определили accuracy, который вы используете для расчета точности модели в accuracy.eval()? это должно быть percent_correct.eval()? - person Kanmani; 01.12.2017

Возможны проблемы:

1- Инициализируйте свои переменные случайным образом, а не нулем

2- Вы можете неправильно понять формат файла .csv, где вы получили файл .csv, сказав, что формат label, pix-11, pix-12, pix-13, ...

3- Попробуйте использовать tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits( logits , llabels )) метод, который вы используете для расчета потерь, численно нестабилен. Обновление: в этом случае не используйте tf.nn.softmax, потому что tf.nn.softmax_cross_entropy_with_logits внутри имеет нормализатор softmax и перекрестную энтропию (спасибо за комментарий @ml4294)

person Ali Abbasi    schedule 25.04.2017
comment
Примечание. Если вы используете tf.nn.softmax_cross_entropy_with_logits(), вам не следует использовать функцию softmax() в вашей функции model(), поскольку встроенная в TensorFlow функция кросс-энтропии softmax ожидает ненормализованные логиты. - person ml4294; 25.04.2017
comment
Спасибо за совет. Пробовал 1 и 3, потом точность стала немного выше (но все равно низкая, 0.53pt). Что касается формата, я сделал метки 10dims one-hot vector. (например, метка 2 соответствует [0,0,1,0,0,0,0,0,0,0]) Тогда это не должно быть ошибкой, я думаю... - person Ted; 26.04.2017
comment
Добро пожаловать, другим предложением может быть увеличение размера пакета, а также попытка перетасовать ваши данные (сначала не пакет, а целые данные), возможно, данные по порядку в файле .csv. - person Ali Abbasi; 26.04.2017