Я кодирую игрушечный пример для данных CSV в Tensorflow.Я реализовал три типа загрузчика данных в tenorflow и pytorch, чтобы сравнить их скорости.Вот код:
Во-первых, с тензорным потоком API tf.data.experimental.CsvDataset
:
def parse_data(x, n_classes):
x = tf.convert_to_tensor(x)
return x[:-1], tf.one_hot(indices=tf.cast(x[-1], tf.int32), depth=n_classes)
if __name__=='__main__':
dataset_train = tf.data.experimental.CsvDataset('/home/david/Dataset/timit/test.csv', [tf.float32] * 430,
header=False,
field_delim=' ')
dataset_train = dataset_train.map(lambda *x_: parse_data(x_, 1928))
dataset_train = dataset_train.batch(128)
dataset_train = dataset_train.prefetch(1)
iterator = dataset_train.make_initializable_iterator()
x_in, y = iterator.get_next()
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x_in)
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x)
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x)
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x)
logits = tf.layers.Dense(units=1928, activation=None)(x)
loss = tf.losses.softmax_cross_entropy(y, logits)
optimizer = tf.train.AdamOptimizer()
optimizer.minimize(loss)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
sess.run(iterator.initializer)
running_loss = 0.0
time_last = time.time()
epoch = 0
i = 0
while True:
try:
running_loss += sess.run(loss) # , feed_dict={x: data, y: labels})
if (i + 1) % 5 == 0:
print('\r[epoch: %2d, batch: %5d, time: %5f] loss: %.3f' % (
epoch + 1, i + 1, time.time() - time_last, running_loss / i), end=' ')
time_last = time.time()
i += 1
except tf.errors.OutOfRangeError:
pass
Во-вторых, с использованием pandas
и tf.placeholder
:
if __name__ == '__main__':
x_in = tf.placeholder(shape=[128, 429], dtype=tf.float32)
y_in = tf.placeholder(shape=[128], dtype=tf.int32)
y = tf.one_hot(y_in, depth=1928)
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x_in)
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x)
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x)
x = tf.layers.Dense(units=1024, activation=tf.nn.relu)(x)
logits = tf.layers.Dense(units=1928, activation=None)(x)
loss = tf.losses.softmax_cross_entropy(y, logits)
optimizer = tf.train.AdamOptimizer()
optimizer.minimize(loss)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
w = pd.read_csv('/home/david/Dataset/timit/test.csv', header=None, delim_whitespace=True).values
for epoch in range(23):
running_loss = 0.0
time_last = time.time()
i = 0
indexes = np.random.permutation(w.shape[0])
w_ = w[indexes, :]
while True:
if i * 128 + 128 > w.shape[0]:
break
running_loss += sess.run(loss,
feed_dict={x_in: w_[i * 128:i * 128 + 128, :-1],
y_in: w_[i * 128:i * 128 + 128, -1]})
if (i + 1) % 5 == 0:
print('\r[epoch: %2d, batch: %5d, time: %5f] loss: %.3f' % (
epoch + 1, i + 1, time.time() - time_last, running_loss / i), end=' ')
time_last = time.time()
i += 1
Третий, с pytorch
и pandas
:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(429, 1024)
self.fc2 = nn.Linear(1024, 1024)
self.fc3 = nn.Linear(1024, 1024)
self.fc4 = nn.Linear(1024, 1024)
self.fc5 = nn.Linear(1024, 1928)
def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = F.relu(self.fc3(x))
x = F.relu(self.fc4(x))
x = self.fc5(x)
return x
class CsvDataset(data.Dataset):
"""Face Landmarks dataset."""
def __init__(self, csv_file):
"""
Args:
csv_file (string): Path to the csv file with annotations.
root_dir (string): Directory with all the images.
transform (callable, optional): Optional transform to be applied
on a sample.
"""
self.landmarks_frame = pd.read_csv(csv_file, header=None, delim_whitespace=True)
def __len__(self):
return len(self.landmarks_frame)
def __getitem__(self, idx):
landmarks = self.landmarks_frame.values[idx, :]
return landmarks[:-1], landmarks[-1]
if __name__ == '__main__':
net = Net()
device = torch.device('cuda:0')
print(device)
net.to(device)
optimizer = optim.Adam(net.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
dataset = CsvDataset('/home/david/Dataset/timit/train.csv')
trainloader = torch.utils.data.DataLoader(dataset, batch_size=128, shuffle=True)
for epoch in range(23):
running_loss = 0.0
time_last = time.time()
for i, data in enumerate(trainloader):
inputs, labels = data
inputs = inputs.float().to(device)
labels = labels.long().to(device)
optimizer.zero_grad()
output = net(inputs)
loss = criterion(output, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if (i + 1) % 5 == 0:
print('\r[epoch: %2d, batch: %5d, time: %5f] loss: %.3f' % (
epoch + 1, i + 1, time.time() - time_last, running_loss / i), end=' ')
time_last = time.time()
print('')
print('Finished Training')
Я записываю затраты времени на обучение в пяти партиях:
- First, CsvDataset: 1.382647s
- Во-вторых, tf.placeholder: 0,013263 с
- В-третьих, pytorch: 0,042086 с
Я полагаю, это отчасти потому, что tf.data.experimental.CsvDataset
выполняет операции ввода-вывода перед каждым пакетом для извлечения данных изCSV-файл (это Ture, или есть другие причины?).
Однако это слишком медленно по сравнению с двумя другими.Есть ли шанс на улучшение?Как настроить tf.data.experimental.CsvDataset
API для загрузки всех данных CSV в самом начале?
Или я могу сказать, что tf.data.experimental.CsvDataset
реализован только для набора данных CSV, который слишком велик для хранения в памяти?Потому что затраты времени кажутся невыносимыми.