Возникает ошибка ‘ValueError: setting an array element with a sequence.’ при попытке обработать данные смешанного типа.

Вопрос или проблема

Я уже видел это, это и это вопрос, но ни одно из предложений не помогло решить мою проблему (поэтому я отменил их).

У меня есть следующий код:

nlp = spacy.load('en_core_web_sm')
parser = English()

class CleanTextTransformer(TransformerMixin):
    def transform(self, X, **transform_params):
        return [cleanText(text) for text in X]

    def fit(self, X, y=None, **fit_params):
        return self

    def get_params(self, deep=True):
        return {}

def cleanText(text):
    text = text.strip().replace("\n", " ").replace("\r", " ")
    text = text.lower()
    return text

def tokenizeText(sample):
    tokens = parser(sample)
    lemmas = []
    for tok in tokens:
        lemmas.append(tok.lemma_.lower().strip() if tok.lemma_ != "-PRON-" else tok.lower_)
    tokens = lemmas
    tokens = [tok for tok in tokens if tok not in STOPLIST]
    tokens = [nlp(tok)[0].lemma_ for tok in tokens if tok not in SYMBOLS]
    return tokens

class multilabelbin(TransformerMixin):
    def __init__(self, *args, **kwargs):
        self.encoder = MultiLabelBinarizer(*args, **kwargs)

    def fit(self, x, y=0):
        self.encoder.fit(x)
        return self

    def transform(self, x, y=0):
        return self.encoder.transform(x)

def represent(rd, ed, number, category, text):
    doc_train = rd
    doc_test = ed

    for column in category:
        doc_train[column] = [tuple(doc.split(",")) for doc in rd[column]]
        doc_test[column] = [tuple(doc.split(",")) for doc in ed[column]]

        print("columns split")

        mlb = multilabelbin(sparse_output=False)
        mlb.fit(doc_train)

        transformed_r = mlb.transform(doc_train)
        for row in range(len(doc_train[column])):
            print(doc_train[column][row])
            doc_train[column][row] = transformed_r[row]

        transformed_e = mlb.transform(doc_test)
        for row in range(len(doc_test[column])):
            print(doc_test[column][row])
            doc_test[column][row] = transformed_e[row]

        print("categorical columns encoded using MultiLabelBinarizer()")

    for column in number:
        ss = StandardScaler()
        ss.fit(doc_train[column].values.reshape(-1, 1))

        doc_train[column] = ss.transform(doc_train[column].values.reshape(-1, 1))
        doc_test[column] = ss.transform(doc_test[column].values.reshape(-1, 1))
        print("numbers scaled using StandardScaler()")

    for column in text:
        cleaner = CleanTextTransformer()
        cleaner.fit(doc_train[column].tolist())

        doc_train[column] = cleaner.transform(doc_train[column])
        doc_test[column] = cleaner.transform(doc_test[column])

        print(doc_train[column])

        vec = TfidfVectorizer(tokenizer=tokenizeText, ngram_range=(1, 1))
        vec.fit(doc_train[column].tolist())

        doc_train[column] = vec.transform(doc_train[column]).todense()
        doc_test[column] = vec.transform(doc_test[column]).todense()

        print(doc_train[column])

        print("text vectorized")

    print("preprocessing completed successfully")

    return doc_train, doc_test

def train_classifier(train_docs, classAxis):
    clf = OneVsRestClassifier(LogisticRegression(solver="saga"))

    X = [list(train_docs[list(train_docs)[i]]) for i in range(1, len(train_docs))]
    y = list(train_docs[classAxis])

    classifier = clf.fit(X, y)
    return classifier

df = pd.DataFrame(pd.read_csv("testdata.csv", header=0))
test_data = pd.DataFrame(pd.read_csv("test.csv", header=0))

train, test = represent(df, test_data, ["Cat2", "Cat5"], ["Cat6"], ["Cat1", "Cat3", "Cat4", "Cat7"])

print(train, test)

model = train_classifier(train, "Class")

train.csv содержит данные в таком формате:

format of data

test.csv имеет тот же формат.

Как вы видите, есть текстовые значения, числовые значения и категориальные значения. Мой код сначала разбивает категориальные значения (которые разделены запятыми), а затем пропускает их через MultiLabelBinarizer(). Затем я просто масштабирую числа. И, наконец, я обрабатываю текст, используя настройки spaCy, найденные в этом руководстве. Я также применяю преобразования к тестовым данным, чтобы не было несовместимости. Наконец, я привожу все к list в функции train_classifier, что якобы должно помочь… но не помогло. В строке classifier = clf.fit(list(X), y) я получаю следующую ошибку:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:\Users\User\AppData\Local\JetBrains\Toolbox\apps\PyCharm-P\ch-0\191.7141.48\helpers\pydev\_pydev_bundle\pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "C:\Users\User\AppData\Local\JetBrains\Toolbox\apps\PyCharm-P\ch-0\191.7141.48\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/Users/User/PycharmProjects/ml/ml.py", line 148, in <module>
    model = train_classifier(train, "Class")
  File "C:/Users/User/PycharmProjects/ml/ml.py", line 124, in train_classifier
    classifier = clf.fit(list(X), y)
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\multiclass.py", line 215, in fit
    for i, column in enumerate(columns))
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\externals\joblib\parallel.py", line 917, in __call__
    if self.dispatch_one_batch(iterator):
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\externals\joblib\parallel.py", line 759, in dispatch_one_batch
    self._dispatch(tasks)
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\externals\joblib\parallel.py", line 716, in _dispatch
    job = self._backend.apply_async(batch, callback=cb)
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\externals\joblib\_parallel_backends.py", line 182, in apply_async
    result = ImmediateResult(func)
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\externals\joblib\_parallel_backends.py", line 549, in __init__
    self.results = batch()
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\externals\joblib\parallel.py", line 225, in __call__
    for func, args, kwargs in self.items]
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\externals\joblib\parallel.py", line 225, in <listcomp>
    for func, args, kwargs in self.items]
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\multiclass.py", line 80, in _fit_binary
    estimator.fit(X, y)
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\linear_model\logistic.py", line 1288, in fit
    accept_large_sparse=solver != 'liblinear')
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\utils\validation.py", line 756, in check_X_y
    estimator=estimator)
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\sklearn\utils\validation.py", line 527, in check_array
    array = np.asarray(array, dtype=dtype, order=order)
  File "C:\Users\User\AppData\Local\Programs\Python\Python36\lib\site-packages\numpy\core\numeric.py", line 538, in asarray
    return array(a, dtype, copy=False, order=order)
ValueError: setting an array element with a sequence.

Я пытался читать документацию, и не избегаю чтения исходного кода (PyCharm помог мне определить источник ошибки), но я не смог приблизиться к её решению. Я чувствую, что перепробовал всё с первых 3 страниц Google, но без успеха.

Как я могу исправить эту ошибку? Почему это происходит? Моя предварительная обработка некорректна? Я знаю, что в некоторых местах она немного сомнительная, но делает ли это её нефункциональной? Если да, как я мог бы исправить эти проблемы в препроцессоре? Исправит ли это ошибку ValueError: setting an array element with a sequence.?

Некоторые заметки:

  • По какой-то причине spaCy возвращает 0.0 для большинства значений в каждом столбце.
  • Я не уверен, могу ли я просто вставить мой вывод MultiLabelVectorizer() в DataFrame вот так (просто как 2D массивы) – это приемлемо? Требуются ли ещё какие-либо шаги?
  • Я пытался использовать конвейеры для более семантического кода, а также использовать разные классификаторы для разных типов данных (например, использовать Chi^2 для текста и другие вещи для других типов), но это всегда приводило к бесконечному потоку ошибок.
  • Я не могу даже определить, что вызывает эту ошибку: это данные столбца, текстовые данные или числовые данные? Я не знаю.

Пакеты, которые вы используете, разработаны для работы в очень определённом порядке, и данные на каждом этапе могут не соответствовать ожидаемым.

Массив NumPy должен иметь однородный dtype/тип данных. Для машинного обучения это должен быть числовой тип данных, обычно float. Если вы попытаетесь передать объектный тип данных в scikit-learn, это не сработает.

Scikit-learn ожидает на вход массивы NumPy, а не списки Python. Если данные останутся массивами NumPy, код, скорее всего, будет работать.

В данный момент вы вручную перебираете данные для их преобразования. Если вы переделаете ваш код таким образом, чтобы в первую очередь использовать конвейеры scikit-learn, это будет более автоматизировано и может привести к более информативным сообщениям об ошибках.

Так как у вас есть неоднородные данные, Feature Union – это лучшая практика для обработки такого рода данных для scikit-learn.

.

Ответ или решение

Для решения проблемы с ошибкой "ValueError: setting an array element with a sequence.", возникающей при обработке данных смешанных типов в Python, важно понять ее природу и распространенные причины. Ваша ошибка связана с тем, что алгоритмы библиотеки scikit-learn ожидают получения данных в виде массивов NumPy, содержащих только числовые значения. Любые отклонения от этого правила могут вызвать подобные ошибки. Давайте разберем проблему более подробно.

Теория

Библиотека scikit-learn широко используется для машинного обучения, и одна из ключевых её особенностей — требование к входным данным. Все данные должны быть представлены в виде числовых массивов NumPy, где каждое значение одного типа данных (чаще всего float). Это необходимо для корректного выполнения математических операций во время обучения модели. Если в массиве встречаются данные другого типа, это может привести к ошибкам.

Пример

В вашей задаче обрабатываются текстовые, числовые и категориальные данные. Кажется, что на каком-то этапе этой обработки данные остаются в неудовлетворительном формате для scikit-learn. Например, использование списков Python вместо массивов NumPy для представления данных может вызвать ошибку, если типы данных оказались разнородными.

Применение

  1. Используйте Pipelines и FeatureUnion: Это позволит автоматически и единообразно обрабатывать данные и выявлять источники ошибок. Например, вы можете создать отдельные конвейеры для различных типов данных (текст, категории, числа) и затем объединить их с помощью FeatureUnion. Это позволит выполнять все преобразования последовательно и гарантирует, что данные будут в корректном формате при поступлении в модель.

  2. Проверяйте типы данных: Убедитесь, что все операции с массивами возвращают данные типа float32 или float64. Преобразовывайте данные в массивы NumPy до их подачи в scikit-learn.

  3. Проводите скалирование и кодирование в отдельных шагах: Убедитесь, что кодирование категориальных переменных и векторизация текстовых данных выполняются с генерацией массивов NumPy соответствующего типа.

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

В итоге ваша задача — удостовериться, что на каждом этапе подготовки данных вы соблюдаете требования scikit-learn к форматам данных. Это повысит шансы на успешную обработку данных без возникновения ошибок. Воспользуйтесь преимуществами автоматизированных конвейеров обработки, чтобы упростить и стабилизировать весь процесс машинного обучения.

Оцените материал
Добавить комментарий

Капча загружается...