Керас использует всю память GPU сразу - PullRequest
0 голосов
/ 30 января 2019

В настоящее время я пытаюсь выполнить статический анализ файлов APK, и у меня есть набор данных приблизительно из 50 000 образцов.Чтобы получить их в формате, который можно использовать в моей сети, каждый APK был декомпилирован и файлы smali объединены, а затем все команды smali в объединенном файле преобразованы в число, и полученный файл представляет собой файл CSV.Затем я пытаюсь использовать указанные файлы в качестве входных данных для сети Keras, но по какой-то причине я продолжаю сталкиваться с ошибками OOM, например, «из-за нехватки памяти, пытающейся выделить 880,21 МБ. Ниже приводится текущая сводная таблица распределения».

Моя системавыглядит следующим образом: 64 ГБ DDR4 RAM GTX 1080 - 8 ГБ VRAM i5 8600

Первым делом я попытался уменьшить сложность сети (уменьшить пространство для встраивания и LSTM)."train_onbatch" функционирует и создает генератор - все еще в коде.Затем я попытался уменьшить размер пакета до 2, хотя это работало, но это было невероятно медленно (прогнозировалось около 600 часов для одной эпохи). После этого я попытался сделать так, чтобы файлы читались в большей памяти, то есть с помощью numpy.массивы против списков и т. д. Наконец, я попытался использовать версию TensorFlow, не относящуюся к gpu, и при этом вся моя 64 ГБ ОЗУ использовалась в течение минуты.

Я также попытался установить настройки конфигурации в TS, т.е. увеличить объем памяти и т. Д., Но не повезло

import os

import numpy as np
import pandas as pd
from keras import Sequential
from keras.layers import Embedding, Conv1D, MaxPooling1D, Dropout, LSTM, Dense
from sklearn.model_selection import train_test_split
from sklearn.utils import shuffle


def read_datasets(path):
    benign = {
        'file_name': np.random.permutation(
            [f for f in os.listdir(os.path.join(path, 'benign')) if
             os.path.isfile(os.path.join(path, 'benign', f))]),
        'label': 0,
        'dir': '/benign'
    }
    malicious = {
        'file_name': np.random.permutation(
            [f for f in os.listdir(os.path.join(path, 'malicious')) if
             os.path.isfile(os.path.join(path, 'malicious', f))]),
        'label': 1,
        'dir': '/malicious'
    }
    b_len = len(benign['file_name'])
    m_len = len(malicious['file_name'])
    result = pd.concat([pd.DataFrame(data=benign, index=[x for x in range(0, b_len)]),
                        pd.DataFrame(data=malicious, index=[x for x in range(b_len + 1, b_len + m_len + 1)])])
    result = shuffle(result)
    result.set_index('file_name', inplace=True)
    return result


def batch_generator(df, batch_size):
    for i in range(0, len(df), batch_size):
        yield preprocess_subset(df[i:i + batch_size]), df['label'][i:i + batch_size]


def get_max_file_len_for_batch(df):
    max_length = float('-inf')
    for row in df.iterrows():
        with open('../../dataset' + os.path.join(row[1]['dir'], 'file_lengths', row[0] + '.length')) as infp:
            x = infp.read()
        if int(x) > max_length:
            max_length = int(x)
    return max_length


def preprocess_subset(df):
    max_file_len = get_max_file_len_for_batch(df)
    X = np.empty((len(df), max_file_len))
    for i, row in enumerate(df.iterrows()):
        data = pd.read_csv('../../dataset' + os.path.join(row[1]['dir'], row[0]), dtype='int16',
                           delimiter=',').values
        if np.max(data) > 256 or np.min(data) < 0:
            print('../../dataset' + os.path.join(row[1]['dir'], row[0]))
        else:
            data = data[data != 0]
            if len(data) > max_file_len:
                max_offset = len(data) - max_file_len
                offset = np.random.randint(max_offset)
                data = data[offset:(max_file_len + offset)]
            else:
                if max_file_len > len(data):
                    max_offset = max_file_len - len(data)
                    offset = np.random.randint(max_offset)
                else:
                    offset = 0
                data = np.pad(data, (offset, max_file_len - len(data) - offset), "constant")
            X[i,] = data
    return X


def model_cnn_lstm():
    max_features = 256
    embedding_size = 50
    model = Sequential()
    model.add(Embedding(max_features, embedding_size))
    model.add(Conv1D(64, 3, padding='valid', activation='relu', strides=1))
    model.add(MaxPooling1D(2, strides=2))
    model.add(Conv1D(64, 3, padding='valid', activation='relu', strides=1))
    model.add(MaxPooling1D(2, strides=2))
    model.add(Dropout(0.5))

    model.add(LSTM(32))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])
    return model


def run():
    df = read_datasets('../../dataset')

    x_train, x_test, y_train, y_test = train_test_split(df.index, df['label'], test_size=0.33, random_state=42)


    curr_model = model_cnn_lstm()
    x_train = preprocess_subset(df.loc[x_train])

    # for x_batch, y_batch, in batch_generator(x_train, 16):
    curr_model.fit(x_train, y_train, batch_size=16, epochs=5)

    curr_model.save('model.hdf5')


run()

1 Ответ

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

Вы можете использовать API tf.data.Dataset. Есть способ создать генератор только из вашего CSV-файла.

dataset = tf.data.experimental.CsvDataset(
    "my_file*.csv",
    [tf.float32,  # Required field, use dtype or empty tensor
     tf.constant([0.0], dtype=tf.float32),  # Optional field, default to 0.0
     tf.int32,  # Required field, use dtype or empty tensor
     ],
    select_cols=[1,2,3]  # Only parse last three columns
)

Но это все-таки не лучший способ.Обучение будет быстрее, если вы конвертируете свой CSV в TFRecords. Здесь хороший пост об этом.

Чтобы решить проблему с OOM, вам все равно нужно выбрать правильный (не большой)) размер пакета и размер буфера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...