Как ввести двумерный массив в Tensorflow? (также о том, как получить матричный ввод и вывод, работая с TF) - PullRequest
0 голосов
/ 21 января 2019

Я новичок в Tensorflow и пытаюсь понять, как он обрабатывает данные. В настоящее время это то, что я хочу иметь в качестве своего вклада. Мой полный код на github , если вы хотите его загрузить.

print (y_train[0])
>>> [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 
1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 
1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 
1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 
0.0, 1.0, 0.0, 1.0, 0.0, 0.0]
# list of 80 elements

print (np.array(y_train))
>>> [[0. 0. 1. ... 1. 0. 0.]
 [0. 1. 0. ... 0. 0. 0.]
 [1. 0. 1. ... 0. 0. 0.]
 ...
 [0. 0. 1. ... 1. 1. 0.]
 [1. 0. 0. ... 0. 0. 1.]
 [0. 0. 0. ... 1. 0. 1.]]

print (np.array(y_train).shape)
>>> (11645, 80)

print (x_train[0])
>>> [1.0, 4.0, 5.0, 2.0, 5.0, 3.0, 5.0, 3.0, 4.0, 5.0, 3.0, 5.0, 4.0, 3.0, 
3.0, 4.0, 5.0, 4.0, 4.0, 5.0, 4.0, 3.0, 3.0, 4.0, 4.0, 5.0]

print (np.array(x_train)/5)
>>> [[0.2 0.8 1.  ... 0.8 0.8 1. ]
[0.6 0.8 1.  ... 1.  1.  0.8]
[0.8 0.4 1.  ... 1.  0.6 1. ]
...
[1.  0.6 0.8 ... 0.4 0.8 0.6]
[1.  0.8 0.8 ... 0.4 0.6 1. ]
[0.6 0.8 0.8 ... 1.  0.8 0.6]]

print (np.array(x_train).shape)
>>> (11645, 26)

Так что в основном у меня есть 11645 частей данных в моем наборе данных. Для входа я хочу иметь 26 входов, нормализованных от 0 до 1. Для выхода я хочу иметь 80 двоичных выходов. Я не думаю, что TF может давать двоичные выходы, поэтому я, вероятно, буду использовать функцию активации сигмоида.

Как мне заставить Tensorflow понять, что у меня есть 11645 фрагментов данных, которые я хочу обработать, и что входная форма должна быть 26x1, а выходная 80x1? Есть некоторые части Tensorflow и Keras, которые я не понимаю, как они сочетаются друг с другом. Например, если я хочу, чтобы Tensorflow понимал, что мой ввод должен быть 1x26, а не какой-либо другой вид ввода, я должен использовать x_train = tf.reshape(x_train, [-1,1*26]) и y_train = tf.reshape(y_train, [-1,1*80])? Из документации кажется, что x_train превратится в тензор только из 1 строки и 26 столбцов, и у меня будет 11645 из них. Но указывает ли это на Tensorflow, что ввод должен быть только 1x26, и он не перестанет захватывать какое-то другое число (например, 26x2). Или я должен сделать что-то более явное, как это, где я указываю форму ввода в модель? model.add(tf.keras.layers.Dense(26, activation=keras.activations.relu, input_shape=(26,)))?

Опять же, для моего вывода я хочу иметь тензор 1x80, который я могу изменить и все такое. Должен ли я явно указать тензор потока? Или что-то вроде model.add(tf.keras.layers.Dense(80, activation=keras.activations.sigmoid)) будет достаточно, чтобы сообщить Tensorflow, что я хочу матрицу 1x80, и (например, для использования сигмоидной функции), что она должна сравнивать каждый фрагмент данных в этом прогнозируемом 1x80 с матрицей 1x80, которую я имею в y_train, с рассчитать функцию потерь?

По сути, я не совсем понимаю, как Tensorflow «знает», какие данные принимать в качестве отдельного ввода и вывода. Есть ли способ указать это или это шаг, который можно пропустить?

РЕДАКТИРОВАТЬ: На основе ответов, я использовал код:

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(26, input_dim=26,activation='relu'))
model.add(tf.keras.layers.Dense(80, activation='sigmoid'))
model.compile(optimizer='rmsprop',
      loss='binary_crossentropy',
      metrics=['accuracy'])
model.fit(x_train, y_train, epochs=10, batch_size=32)

Я получаю следующую матрицу:

[0.38176608 0.34900635 0.36545524 0.36806932 0.36692804 0.37398493
  0.36821148 0.35577637 0.38441166 0.3676901  0.41162464 0.40428266
  0.41464344 0.4040607  0.39316037 0.428753   0.3547327  0.35693064
  0.3422352  0.36919317 0.36431065 0.3515264  0.3889933  0.33974153
  0.37329385 0.35898593 0.3891792  0.42334762 0.40694237 0.41910493
  0.39983115 0.47813386 0.37625512 0.35567597 0.36811477 0.38242644
  0.36549032 0.35696995 0.37058106 0.3556903  0.37096408 0.34965912
  0.4247738  0.41512045 0.41622216 0.38645518 0.40850884 0.43454456
  0.3655926  0.34644917 0.36782715 0.34224963 0.35035127 0.3502
  0.3607877  0.38218996 0.37265536 0.3653391  0.41620222 0.41124558
  0.3916335  0.41291553 0.39959764 0.4649614  0.34603494 0.36731967
  0.34146535 0.34573284 0.33941117 0.35885242 0.3493014  0.35866526
  0.37188208 0.34971312 0.38165745 0.3962399  0.38913697 0.4078925
  0.38799426 0.4709055 ]

Это очень далеко от матрицы 0 и 1, которую я хочу. Что я должен сделать, чтобы приблизиться к этому? Я пробовал погуглить мою проблему, но безрезультатно. Должен ли я просто применить к этому пороговое значение (например, 0,4?) И преобразовать его в двоичную матрицу таким образом?

1 Ответ

0 голосов
/ 21 января 2019

Обычно в тензорном потоке мы указываем заполнители при создании графика. Они определяют типы данных, форму и иногда имя входных данных. Базовый пример, соответствующий вашему коду:

x = tf.placeholder(tf.float32,[None,26])
y = tf.placeholder(tf.float32,[None,80])
W = tf.get_variable('W',shape=[26,80],initializer=tf.truncated_normal_initializer(mean=0.0, stddev=0.01))
output = tf.matmul(x,W)
cost = tf.losses.sigmoid_cross_entropy(y,outputs,reduction=tf.losses.Reduction.MEAN)
with tf.Session() as sess:
    loss = sess.run(cost,feed_dict={x:your_input_here,y:your_output_here})

Итак, тензор потока знает, насколько велик ваш ввод, потому что вы его указали, и использует его для расчета формы вывода каждого из последующих слоев. Пакетное измерение (первое измерение) не имеет значения, потому что это может быть переменная, как если бы ваш ввод был размером [50x26], ваш вывод был бы размером [50,80]. Количество образцов данных не имеет значения, потому что вы можете вводить их в модель по своему усмотрению.

Но в керасе все немного проще:

model = Sequential()
model.add(Dense(32, input_dim=26,activation='relu'))
model.add(Dense(80,activation='sigmoid'))
model.compile(optimizer='rmsprop',
          loss='binary_crossentropy',
          metrics=['accuracy'])
model.fit(data, labels, epochs=10, batch_size=32)

Вы видите, что мы должны указать входные размеры в первом слое, и опять же, размер партии указывать не нужно. Затем можно указать выходной слой такой же формы, что и ожидаемое количество выходов.

Кроме того, в качестве примечания я бы порекомендовал вам разбивать данные на пакеты (где-то между 10 и 200 сэмплами, в зависимости от памяти / производительности), а не вставлять сразу все 11k сэмплов!

...