Предсказание выбросов с категориальными данными в библиотеке Pythons Scikit-Learn - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь сделать прогноз со своим собственным выводом. Я использую Python Scikit-learn lib и Isolation Forest в качестве алгоритма. Я не знаю, что я делаю неправильно, но когда я хочу преобразовать свои входные данные, я всегда получаю сообщение об ошибке. Я получаю ошибку в этой строке:

    input_par = encoder.transform(val)#ERROR

это ошибка: Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.

И я пробовал это, но я всегда получаю ошибку:

    input_par = encoder.transform([val])#ERROR

это ошибка: alueError: Specifying the columns using strings is only supported for pandas DataFrames

Что я делаю не так, как я могу исправить эту ошибку? Кроме того, я должен использовать OneHotEncoder, LabelEncoder или CountVectorizer?

Это мой код:

import pandas as pd

from sklearn.ensemble import IsolationForest
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, LabelEncoder

textual_data = ['i love you', 'I love your dress', 'i like that', 'thats good', 'amazing', 'wrong', 'hi, how are you, are you doing good']
num_data = [4, 1, 3, 2, 65, 3,3]

df = pd.DataFrame({'my text': textual_data,
                   'num data': num_data})
x = df

# Transform the features
encoder = ColumnTransformer(transformers=[('onehot', OneHotEncoder(), ['my text'])], remainder='passthrough')
#encoder = ColumnTransformer(transformers=[('lab', LabelEncoder(), ['my text'])])

x = encoder.fit_transform(x)

isolation_forest = IsolationForest(contamination = 'auto', behaviour = 'new')
model = isolation_forest.fit(x)

list_of_val = [['good work',2], ['you are wrong',54], ['this was amazing',1]]

for val in list_of_val:

    input_par = encoder.transform(val)#ERROR

    outlier = model.predict(input_par)
    #print(outlier)

    if outlier[0] == -1:
        print('Values', val, 'are outliers')

    else:
        print('Values', val, 'are not outliers')

РЕДАКТИРОВАТЬ:

Я также пробовал это:

list_of_val = [['good work',2], ['you are wrong',54], ['this was amazing',1]]

for val in list_of_val:

    input_par = encoder.transform(pd.DataFrame({'my text': val[0],
                                               'num data': val[1]}))

Но я получаю эту ошибку:

ValueError: If using all scalar values, you must pass an index

Ответы [ 4 ]

2 голосов
/ 13 октября 2019

Я постараюсь составить список наблюдений, который вам может пригодиться:

  • LabelEncoder можно использовать, например, для преобразования нечисловых данных в числовыеэтикетки. OneHotEncoder обычно принимает числовые или нечисловые данные и преобразует их, ну, в общем, в горячие кодировки. Оба обычно используются для предварительной обработки «меток» (классов контролируемой задачи обучения).
  • Насколько я понимаю, вы пытаетесь предсказать выбросы (обнаружение аномалий). Мне не ясно, является ли связь между высказываниями и целыми числами только жестко запрограммированной, или если вы хотите каким-то образом создать такую ​​связь. Если это то, что вам нужно, то вы не сможете добиться этого с помощью ранее упомянутых кодеров, потому что вы подгоняете их к некоторым данным (которые, как правило, должны быть метками) и пытаетесь преобразовать новые несвязанные данные (ValueError: y содержит ранее невидимые метки),Однако это можно исправить, установив параметр handle_unknown в OneHotEncoder в значение «ignore» (из документации: «Вызывать ли ошибку или игнорировать, если во время преобразования присутствует неизвестная категориальная функция»). Даже если вы можете достичь того, чего хотите, с помощью одного из этих кодировщиков, вы должны помнить, что это не является его главной целью.
  • Я предполагаю, что вы придаете большое значение "отрицательному"высказывания (даже если «неправильно» не соответствует 65 в ваших данных поезда) и небольшое значение для «положительных». Если вы предполагаете, что вы уже знаете каждое целое число для каждого высказывания, вы можете обучить модель на том, что считается «положительным» примером, и давать «отрицательные» примеры (выбросы) только при тестировании. Вы не обучаете IsolationForest на «положительных» и «отрицательных» примерах - это будет просто базовая двоичная классификация, которую можно смоделировать, например, с помощью дерева решений. Интуитивно понятный пример IsolationForest можно увидеть здесь . Ниже приведен код вашей проблемы:

    import numpy as np
    from sklearn.ensemble import IsolationForest
    
    textual_data = ['i love you', 'I love your dress', 'i like that', 'thats good', 'amazing', ...]
    integer_connection = [1, 1, 2, 3, 2, 2, 3, 1, 3, 4, 1, 2, 1, 2, 1, 2, 1, 1]
    integer_connection = np.array([[n] for n in integer_connection])
    
    isolation_forest = IsolationForest(contamination = 'auto', behaviour = 'new')
    isolation_forest.fit(integer_encoded)
    
    list_of_val = [['good work', 2], ['you are wrong', 54], ['this was amazing', 1]]
    
    text_vals = [d[0] for d in list_of_val]
    numeric_vals = np.array([[d[1]] for d in list_of_val])
    
    print(integer_encoded, numeric_vals)
    
    outliers = isolation_forest.predict(numeric_vals)
    print(outliers)
    
  • В целом, я не думаю, что ваш подход является правильным в отношении прогнозирования выбросов для естественных языковых высказываний. Для того, что вы пытаетесь сделать в этом конкретном примере, я могу порекомендовать использовать сходство векторов слов, например, с spaCy , или, возможно, с простым подходом к сумме слов.

  • Если вам не важен какой-либо из этих пунктов и вам нужен только рабочий код, вот моя версия того, что вы пытаетесь сделать:

    import numpy as np
    
    from sklearn.ensemble import IsolationForest
    from sklearn.compose import ColumnTransformer
    from sklearn.preprocessing import OneHotEncoder, LabelEncoder
    
    
    textual_data = ['i love you', 'I love your dress', 'i like that', 'thats good', 'amazing', 'wrong', 'hi, how are you, are you doing good']
    
    
    encodings = {}
    
    num_data = [4, 1, 3, 2, 65, 3, 3]
    
    
    onehot_encoder = OneHotEncoder(handle_unknown='ignore')
    onehots = onehot_encoder.fit_transform(np.array([[utt, no] for utt, no in zip(textual_data, num_data)]))
    
    for i, l in enumerate(onehots):
        original_label = (textual_data[i], num_data[i])
        encodings[original_label] = l
    
    print(encodings)
    
    isolation_forest = IsolationForest(contamination = 'auto', behaviour = 'new')
    model = isolation_forest.fit(onehots)
    
    list_of_val = [['good work', 2], ['you are wrong', 54], ['this was amazing', 1]]
    
    
    test_encoded = onehot_encoder.transform(np.array(list_of_val))
    print(test_encoded)
    
    outliers = isolation_forest.predict(test_encoded)
    print(outliers)
    
    for i, outlier in enumerate(outliers):
        if outlier == -1:
            print('Values', list_of_val[i], 'are outliers')
    
        else:
            print('Values', list_of_val[i], 'are not outliers')
    
1 голос
/ 09 октября 2019

Вы уверены, что имеет смысл, что вы делаете? Ваш OneHotEncoder() кодирует вашу категориальную переменную ('my text'), используя схему кодирования «горячая» (или «фиктивная»). Думайте об этом как о соответствии между вашими метками и числовым возвратом.

В вашем textual_data у вас есть 7 разных меток: ['i love you', 'I love your dress', 'i like that', 'thats good', 'amazing', 'wrong', 'hi, how are you, are you doing good']. Каждый из них будет закодирован. Это происходит во время:

>>> x = encoder.fit_transform(x)
>>> print(x)
<7x8 sparse matrix of type '<class 'numpy.float64'>'
    with 14 stored elements in Compressed Sparse Row format>

Здесь ваш кодировщик создает отображение для всех 7 меток.

Когда вы продолжаете работу со своим сценарием и хотите использовать тот же кодировщик для преобразования новой метки, еготерпит неудачу:

>>> to_predict = pd.DataFrame({'my text': ['good work', 'you are wrong', 'this was amazing'],
                               'num data': [2, 54, 1]})
>>> encoder.transform(to_predict)
ValueError: Found unknown categories ['this was amazing', 'good work', 'you are wrong'] in column 0 during transform

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

>>> to_predict = pd.DataFrame({'my text': ['i like that', 'i love you', 'i love you'],
                               'num data': [2, 54, 1]})
>>> encoder.transform(to_predict)
<3x8 sparse matrix of type '<class 'numpy.float64'>'
    with 6 stored elements in Compressed Sparse Row format>

Вместо этого вы можете добавить новые наблюдения с новыми метками к исходному df и проведите их снова через ваш конвейер, чтобы они стали частью вашего отображения.

Я должен признать, что я совсем не опытен с этим, поэтому, пожалуйста, поправьте меня, если я ошибаюсь, но это таксмотрит на меняУдачи в вашем проекте.

0 голосов
/ 07 октября 2019

Попробуйте преобразовать ваш список list_of_val в массив numpy, запустив

import numpy as np
list_of_val = np.asarray(list_of_val)
0 голосов
/ 07 октября 2019

у вас очень похожая проблема с

AttributeError при использовании ColumnTransformer в конвейер

Как описано там, рекомендуется использовать pandas для вашей кодировки (тамтакже пример для горячего кодирования). Надеюсь, это поможет!

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