Создание генератора из списка последовательностей для RNN

Мне нужно создать генератор, чтобы мои данные передавались в мою обучающую функцию RNN. У меня есть список образцов пациентов, где каждый образец представляет собой временной ряд длиной ni (который, к сожалению, варьируется) в трех измерениях, и я хочу создать пакеты данные, в которых каждый образец в партии принадлежит только одному пациенту, но каждая партия может содержать несколько образцов пациентов. Выполнение этого таким образом должно максимизировать количество образцов, которые я могу обучить, используя без каких-либо последствий, поскольку моя RNN не с сохранением состояния. Сначала у меня была следующая функция

def dataIterator(rawDataList, config):
    batchSize, nSteps = config.batchSize, config.nSteps
    for rawData in rawDataList:
        dataLen, dataWidth = rawData.shape
        batchLen = dataLen // batchSize
        data = np.zeros([batchSize, batchLen, dataWidth], dtype=np.float32)
        for i in xrange(batchSize):
            data[i] = rawData[batchLen*i:batchLen*(i+1), :]

        epochSize = (batchLen - 1) // nSteps

        if epochSize == 0:
            raise ValueError('epoch_size == 0')

        for i in xrange(epochSize):
            x = data[:, i*nSteps:(i+1)*nSteps, :]
            y = data[:, i*nSteps+1:(i+1)*nSteps+1, :]
            yield (x, y)

Однако при этом каждый образец пациента обрезается, чтобы соответствовать размеру партии. Поэтому я хочу что-то, что создает все возможные партии, включая маленькую в конце. Однако мое незнание генераторов привело меня в замешательство. Пока я понял, что нужно будет использовать арифметику по модулю, но как именно я не уверен, поэтому я добрался только до этого момента:

def dataIterator(data, batchSize=batchSize, nSteps=nSteps, nDimensions=3):
    nTimePoints = sum([len(x) for x in data])
    totalBatchLen = 1+(nTimePoints-1)//batchSize
    newData = np.zeros([batchSize, totalBatchLen, nDimensions])
    for i in xrange(batchSize):
        ...

EDIT Вот краткий пример, показывающий, как решить проблему без использования генераторов.

import numpy as np
np.random.seed(42)
nPatients = 3
tsLength = 5
nDimensions = 3
rnnTSLength = 3
batchSize = 3
inputData = np.random.random((nPatients, tsLength, nDimensions))
inputData[1, :, :] *= 10
inputData[2, :, :] *= 100
outputData = []
for i in xrange(tsLength-rnnTSLength):
    outputData.append(inputData[0, i:i+rnnTSLength, :])
for i in xrange(tsLength-rnnTSLength):
    outputData.append(inputData[1, i:i+rnnTSLength, :])
for i in xrange(tsLength-rnnTSLength):
    outputData.append(inputData[2, i:i+rnnTSLength, :])
temp1 = np.array(outputData[:3])
temp2 = np.array(outputData[3:])
npOutput = np.array((temp1, temp2))
print npOutput

Что производит:

[[[[  3.74540119e-01   9.50714306e-01   7.31993942e-01]
[  5.98658484e-01   1.56018640e-01   1.55994520e-01]
[  5.80836122e-02   8.66176146e-01   6.01115012e-01]]

[[  5.98658484e-01   1.56018640e-01   1.55994520e-01]
[  5.80836122e-02   8.66176146e-01   6.01115012e-01]
[  7.08072578e-01   2.05844943e-02   9.69909852e-01]]

[[  1.83404510e+00   3.04242243e+00   5.24756432e+00]
[  4.31945019e+00   2.91229140e+00   6.11852895e+00]
[  1.39493861e+00   2.92144649e+00   3.66361843e+00]]]


[[[  4.31945019e+00   2.91229140e+00   6.11852895e+00]
[  1.39493861e+00   2.92144649e+00   3.66361843e+00]
[  4.56069984e+00   7.85175961e+00   1.99673782e+00]]

[[  6.07544852e+01   1.70524124e+01   6.50515930e+00]
[  9.48885537e+01   9.65632033e+01   8.08397348e+01]
[  3.04613769e+01   9.76721140e+00   6.84233027e+01]]

[[  9.48885537e+01   9.65632033e+01   8.08397348e+01]
[  3.04613769e+01   9.76721140e+00   6.84233027e+01]
[  4.40152494e+01   1.22038235e+01   4.95176910e+01]]]]

Который, как вы можете видеть, имеет две партии размером три, каждая из которых содержит двух разных «пациентов», но временные ряды для каждого «пациента» не перекрываются.


person piman314    schedule 23.03.2016    source источник
comment
Можете ли вы добавить пример ввода и ожидаемого результата?   -  person Padraic Cunningham    schedule 01.04.2016
comment
Добавлено, извините за медленный ответ.   -  person piman314    schedule 06.04.2016


Ответы (1)


Не совсем понятно, что вы ищете. Небольшая выборка входных данных и желаемого результата может помочь. Тем не менее, я попробую то, о чем, как мне кажется, вы спрашиваете:

def dataIterator(data, batchSize=batchSize):
    for patient_data in data:
        for n in range(0, len(patient_data), batchSize):
            yield patient_data[n:n+batchSize]
person RootTwo    schedule 02.04.2016
comment
Я только что добавил пример ввода и вывода, извините за медленный ответ. - person piman314; 06.04.2016