Вопрос или проблема
Я уже видел это, это и это вопрос, но ни одно из предложений не помогло решить мою проблему (поэтому я отменил их).
У меня есть следующий код:
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
содержит данные в таком формате:
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 для представления данных может вызвать ошибку, если типы данных оказались разнородными.
Применение
-
Используйте Pipelines и FeatureUnion: Это позволит автоматически и единообразно обрабатывать данные и выявлять источники ошибок. Например, вы можете создать отдельные конвейеры для различных типов данных (текст, категории, числа) и затем объединить их с помощью
FeatureUnion
. Это позволит выполнять все преобразования последовательно и гарантирует, что данные будут в корректном формате при поступлении в модель. -
Проверяйте типы данных: Убедитесь, что все операции с массивами возвращают данные типа float32 или float64. Преобразовывайте данные в массивы NumPy до их подачи в scikit-learn.
-
Проводите скалирование и кодирование в отдельных шагах: Убедитесь, что кодирование категориальных переменных и векторизация текстовых данных выполняются с генерацией массивов NumPy соответствующего типа.
-
Тестируйте преобразования на небольших объемах данных: Перед применением всего процесса к набору данных, выполните его на нескольких строках, чтобы обнаружить ошибки на ранних этапах.
В итоге ваша задача — удостовериться, что на каждом этапе подготовки данных вы соблюдаете требования scikit-learn к форматам данных. Это повысит шансы на успешную обработку данных без возникновения ошибок. Воспользуйтесь преимуществами автоматизированных конвейеров обработки, чтобы упростить и стабилизировать весь процесс машинного обучения.