Использование разреженных матриц с Keras и Tensorflow

Мои данные можно рассматривать как матрицу из 10B записей (100M x 100), что очень мало (<1/100 * 1/100 записей не равны нулю). Я хотел бы передать данные в созданную мной модель нейронной сети Keras, используя бэкэнд Tensorflow.

Моей первой мыслью было расширить данные, чтобы они были плотными, то есть записать все записи 10B в серию CSV, причем большинство записей равно нулю. Тем не менее, это быстро ошеломляет мои ресурсы (даже выполнение ETL перегружает панд и заставляет postgres бороться). Поэтому мне нужно использовать истинные разреженные матрицы.

Как я могу сделать это с Keras (и Tensorflow)? В то время как Numpy не поддерживает разреженные матрицы, Scipy и Tenorflow оба поддерживают. Там много обсуждений (например, https://github.com/fchollet/keras/pull/1886 https://github.com/fchollet/keras/pull/3695/files https://github.com/pplonski/keras- sparse-проверьте https://groups.google.com/forum/#!topic/keras-users/odsQBcNCdZg) об этой идее - либо с помощью скудных разреженных матриц, либо перейдя непосредственно к разреженным матрицам Tensorflow. Но я не могу найти четкого заключения, и я не смог заставить что-либо работать (или даже четко знать, куда идти!).

Как я могу это сделать?

Я считаю, что есть два возможных подхода:

  1. Сохраняйте его как скудную разреженную матрицу, а затем, давая Керасу мини-пакет, сделайте его плотным
  2. Держите его разреженным и используйте Tensorflow Sparse Tensors

Я также думаю, что # 2 предпочтительнее, потому что вы получите намного лучшую производительность на всем протяжении (я верю), но # 1, вероятно, проще и будет адекватным. Я буду счастлив с любым из них.

Как это можно реализовать?

Ответ 1

Извините, у меня нет репутации, чтобы комментировать, но я думаю, вам стоит взглянуть на ответ здесь: Keras, проблема с разреженной матрицей. Я пробовал это, и он работает правильно, только одна нота, хотя, по крайней мере, в моем случае, перетасовка привела к действительно плохим результатам, поэтому я использовал эту слегка измененную альтернативу:

def nn_batch_generator(X_data, y_data, batch_size):
    samples_per_epoch = X_data.shape[0]
    number_of_batches = samples_per_epoch/batch_size
    counter=0
    index = np.arange(np.shape(y_data)[0])
    while 1:
        index_batch = index[batch_size*counter:batch_size*(counter+1)]
        X_batch = X_data[index_batch,:].todense()
        y_batch = y_data[index_batch]
        counter += 1
        yield np.array(X_batch),y_batch
        if (counter > number_of_batches):
            counter=0

Он дает сопоставимую точность с теми, которые достигаются при реализации keras shuffled (установка shuffle=True в fit).

Ответ 2

Этот ответ касается второго подхода, упомянутого в вопросе. Можно использовать разреженные матрицы в качестве входных данных для модели Keras с бэкэндом Tensorflow, если вы пишете пользовательский цикл обучения. В приведенном ниже примере модель принимает разреженную матрицу в качестве входных данных и выводит плотную матрицу.

from keras.layers import Dense, Input
from keras.models import Model
import scipy
import numpy as np

trainX = scipy.sparse.random(1024, 1024)
trainY = np.random.rand(1024, 1024)

inputs = Input(shape=(trainX.shape[1],), sparse=True)
outputs = Dense(trainY.shape[1], activation='softmax')(inputs)
model = Model(inputs=inputs, outputs=outputs)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

steps = 10
for i in range(steps):
  # For simplicity, we directly use trainX and trainY in this example
  # Usually, this is where batches are prepared
  print(model.train_on_batch(trainX, trainY))
# [3549.2546, 0.0]
# ...
# [3545.6448, 0.0009765625]

Однако полезность этого подхода зависит от того, должна ли ваша модель уплотнять разреженную матрицу. Действительно, в приведенной выше модели есть один слой, который превращает разреженную матрицу в плотную. Это может быть проблемой, если ваша разреженная матрица не помещается в памяти.