В Python/Tensorflow: как преобразовать строковое представление 2D-массивов из текстовых файлов во что-то, что может использовать TF

#python #pandas #numpy #tensorflow

Вопрос:

Мне нужно загрузить из текстовых файлов строки, содержащие строковые представления 2D-массивов, для последующего использования при обучении Tensorflow CNN, но я не могу преобразовать строки в формат, который нравится Tensorflow. Я пробовал всевозможные комбинации apply/map/различных функций, но всегда получал какую-то загадочную ошибку. Ниже приведен пример кода игрушки, который близок к работе, но все равно выдает ошибку:

 ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type numpy.ndarray)
 
 import tensorflow as tf
import numpy as np
import pandas as pd
from ast import literal_eval

def df_to_dataset(dataframe):
    Y = tf.convert_to_tensor( dataframe['Y'].values )
    X = tf.convert_to_tensor( dataframe['X'].apply(literal_eval).apply(np.array).values )
    return tf.data.Dataset.from_tensor_slices( ( X , Y ) )

data = [[ 1, "[[0,1],[0,1]]" ] , [ 0 , "[[1,0],[1,0]]" ]]
df = pd.DataFrame(data, columns=['Y','X'])
dataset = df_to_dataset(df)
for feature in dataset.take(1):
    print( feature )
 

Комментарии:

1. Как вы ожидаете, что конечный кадр данных будет выглядеть в вашем примере? Для меня это не очевидно.

Ответ №1:

Таким образом, ваш фрейм данных отображается как:

 In [161]: df
Out[161]: 
   Y              X
0  1  [[0,1],[0,1]]
1  0  [[1,0],[1,0]]
 

хотя это не показывает строковые кавычки.

 In [162]: df['Y'].values
Out[162]: array([1, 0])
 

X Столбец представляет собой 1d массив строк, тип объекта dtype:

 In [163]: df['X'].values
Out[163]: array(['[[0,1],[0,1]]', '[[1,0],[1,0]]'], dtype=object)
 

С помощью eval values теперь представляет собой массив списков:

 In [164]: from ast import literal_eval
In [165]: df['X'].apply(literal_eval)
Out[165]: 
0    [[0, 1], [0, 1]]
1    [[1, 0], [1, 0]]
Name: X, dtype: object
In [166]: df['X'].apply(literal_eval).values
Out[166]: array([list([[0, 1], [0, 1]]), list([[1, 0], [1, 0]])], dtype=object)
 

Но если вместо этого мы извлекем его в виде списка:

 In [168]: df['X'].apply(literal_eval).to_list()
Out[168]: [[[0, 1], [0, 1]], [[1, 0], [1, 0]]]
 

Мы можем легко превратить это в массив:

 In [169]: np.array(_)
Out[169]: 
array([[[0, 1],
        [0, 1]],

       [[1, 0],
        [1, 0]]])
 

Возвращаясь к форме массива, мы можем «уменьшить» это, используя stack

 In [170]: np.stack(df['X'].apply(literal_eval).values)
Out[170]: 
array([[[0, 1],
        [0, 1]],

       [[1, 0],
        [1, 0]]])
 

stack похоже concatenate или vstack за исключением того, что это добавляет измерение, действуя более похоже np.array .

Теперь преобразование тензорного потока должно работать.

Ваш второй apply , только изменяет массив списков в массив массивов.

 In [174]: df['X'].apply(literal_eval).apply(np.array).values
Out[174]: 
array([array([[0, 1],
              [0, 1]]), array([[1, 0],
                               [1, 0]])], dtype=object)
 

np.stack работает и над этим тоже.