Scikit-Learn использование памяти классификации текста из ядра

Я пытаюсь использовать scikit-learn для классификации большого количества текстовых документов, хотя я использую неосновную функциональность (с SGDClassifier а также HashingVectorizer) программа, кажется, потребляет много оперативной памяти (>10 ГБ). До этого я выполнял лемматизацию и удалял стоп-слова из текстовых данных. Я чувствую, что упускаю что-то важное здесь. Можете ли вы обнаружить ошибку в моем коде?

Большое спасибо за любое предложение!

Это мой код Python:

import time
import numpy as np
import os
import re
import pyprind
from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.linear_model import SGDClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics

directory = "mydirectory"
batch_size = 1000
n_batches = 44
pbar = pyprind.ProgBar(n_batches)

class Doc_Iterable:
    def __init__(self, file):
        self.file = file
    def __iter__(self):
        for line in self.file:
            line = re.sub('[^\w\s]|(.\d{1,4}[\./]\d{1,2}[\./]\d{1,4})|(\s\d{1,})', '', line)
            yield line


def stream_docs(path, texts_file, labels_file):
    with open(path + texts_file, 'r') as fX, open(path + labels_file, 'r') as fy:
        for text in fX:
            label = next(fy)
            text = re.sub('[^\w\s]|(.\d{1,4}[\./]\d{1,2}[\./]\d{1,4})|(\s\d{1,})', '', text)
            yield text, label

def get_minibatch(doc_stream, size):
    X, y = [], []
    for _ in range(size):
        text, label = next(doc_stream)
        X.append(text)
        y.append(label)
    return X, y


classes = set()
for label in open(directory + 'y_train', 'r'):
    classes.add(label)
for label in open(directory + 'y_test', 'r'):
    classes.add(label)
classes = list(classes)

validation_scores = []
training_set_size = []

h_vectorizer = HashingVectorizer(lowercase=True, ngram_range=(1,1))
clf = SGDClassifier(loss='hinge', n_iter=5, alpha=1e-4, shuffle=True)

doc_stream = stream_docs(path=directory, texts_file='X_train', labels_file='y_train')
n_samples = 0
iteration = 0

for _ in range(n_batches):
    print("Training with batch nr.", iteration)
    iteration += 1

    X_train, y_train = get_minibatch(doc_stream, size=batch_size)

    n_samples += len(X_train)

    X_train = h_vectorizer.transform(X_train)

    clf.partial_fit(X_train, y_train, classes=classes)

    pbar.update()


del X_train
del y_train
print("Training complete. Classifier trained with " + str(n_samples) + " samples.")
print()
print("Testing...")
print()
X_test = h_vectorizer.transform(Doc_Iterable(open(directory + 'X_test')))
y_test = np.genfromtxt(directory + 'y_test', dtype=None, delimiter='|').astype(str)
prediction = clf.predict(X_test)
score = metrics.accuracy_score(y_test, prediction)
print("Accuracy: ", score)
print()

2 ответа

Решение

Попробуйте настроить n_features в HashingVectorizer, например:

h_vectorizer = HashingVectorizer(n_features=10000, lowercase=True, ngram_range=(1,1))

С параметрами по умолчанию (n_features=1048576) вы можете ожидать, что ваша преобразованная матрица будет иметь до:

1048576(features) x 1000(mini batch size) x 8 bytes = 8.4 GB

Это будет меньше, чем из-за разреженности, но коэффициенты классификатора будут складываться:

1048576(features) x len(classes) * 8 bytes

так что это может объяснить ваше текущее использование памяти.

Возможно, это не ответ (извините, если я не смог прокомментировать это из-за проблем с репутацией), но я работал над проектом классификации изображений.

Исходя из моего опыта, обучение с использованием scikit-learn было очень медленным (в моем случае я использовал около 30 изображений, на обучение классификатора у меня ушло почти 2-6 минут). Когда я переключился на OpenCV-python, мне потребовалось всего около минуты или меньше, чтобы обучить один и тот же классификатор, используя то же количество обучающих данных.

Другие вопросы по тегам