Различные типы функций для обучения Наивного Байеса в Python Pandas

Я хотел бы использовать ряд возможностей для обучения с наивным байесовским классификатором для классификации "А" или "не-А".

У меня есть три особенности различных типов значений: 1) total_length - в положительном целом числе 2) vowel-ratio - в десятичной / дробной части 3) twoLetters_lastName - массив, содержащий несколько двухбуквенных строк

# coding=utf-8
from nltk.corpus import names
import nltk
import random
import numpy as np
import pandas as pd
from pandas import DataFrame, Series
from sklearn.naive_bayes import GaussianNB
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

# Import data into pandas
data = pd.read_csv('XYZ.csv', header=0, encoding='utf-8', 
    low_memory=False)
df = DataFrame(data)

# Randomize records
df = df.reindex(np.random.permutation(df.index))

# Assign column into label Y
df_Y = df[df.AScan.notnull()][['AScan']].values # Labels are 'A' or 'non-A'
#print df_Y

# Assign column vector into attribute X
df_X = df[df.AScan.notnull()][['total_length', 'vowel_ratio', 'twoLetters_lastName']].values
#print df_X[0:10]

# Incorporate X and Y into ML algorithms
clf = GaussianNB()
clf.fit(df_X, df_Y)

df_Y выглядит следующим образом:

[[u'non-A']
 [u'A']
 [u'non-A']
 ..., 
 [u'A']
 [u'non-A']
 [u'non-A']]

df_X ниже:

[[9L 0.222222222 u"[u'ke', u'el', u'll', u'ly']"]
 [17L 0.41176470600000004
  u"[u'ma', u'ar', u'rg', u'ga', u'ar', u'ri', u'is']"]
 [11L 0.454545455 u"[u'du', u'ub', u'bu', u'uc']"]
 [11L 0.454545455 u"[u'ma', u'ah', u'he', u'er']"]
 [15L 0.333333333 u"[u'ma', u'ag', u'ge', u'ee']"]
 [13L 0.307692308 u"[u'jo', u'on', u'ne', u'es']"]
 [12L 0.41666666700000005
  u"[u'le', u'ef', u'f\\xe8', u'\\xe8v', u'vr', u're']"]
 [15L 0.26666666699999997 u"[u'ni', u'ib', u'bl', u'le', u'et', u'tt']"]
 [15L 0.333333333 u"[u'ki', u'in', u'ns', u'sa', u'al', u'll', u'la']"]
 [11L 0.363636364 u"[u'mc', u'cn', u'ne', u'ei', u'il']"]]

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

E:\Program Files Extra\Python27\lib\site-packages\sklearn\naive_bayes.py:150: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  y = column_or_1d(y, warn=True)
Traceback (most recent call last):
  File "C:werwer\wer\wer.py", line 32, in <module>
    clf.fit(df_X, df_Y)
  File "E:\Program Files Extra\Python27\lib\site-packages\sklearn\naive_bayes.py", line 163, in fit
    self.theta_[i, :] = np.mean(Xi, axis=0)
  File "E:\Program Files Extra\Python27\lib\site-packages\numpy\core\fromnumeric.py", line 2727, in mean
    out=out, keepdims=keepdims)
  File "E:\Program Files Extra\Python27\lib\site-packages\numpy\core\_methods.py", line 69, in _mean
    ret, rcount, out=ret, casting='unsafe', subok=False)
TypeError: unsupported operand type(s) for /: 'unicode' and 'long'

Насколько я понимаю, мне нужно преобразовать объекты в один массивный массив как вектор объектов, но я не думаю, что готовлю этот X-вектор правильно, поскольку он содержит очень разные типы значений.

2 ответа

Решение

Вопросы, связанные с данной: Выбор алгоритма классификации для классификации смеси номинальных и числовых данных - Смешивание категориальных и непрерывных данных в наивном байесовском классификаторе с использованием Scikit-learn

Хорошо, так что происходит несколько вещей. Как отметил DalekSec, рекомендуется хранить все ваши функции в одном виде, когда вы вводите их в такую ​​модель, как GaussianNB, Трассировка указывает, что при подгонке модели она пытается разделить строку (предположительно одну из ваших строк в кодировке Unicode, например u"[u'ke', u'el', u'll', u'ly']") целым числом. Так что нам нужно преобразовать данные обучения в форму, которую может использовать sklearn. Мы можем сделать это несколькими способами, два из которых Огризель красноречиво описывает в этом ответе здесь.

  1. Мы можем преобразовать все непрерывные переменные в категориальные переменные. В нашем случае это означает преобразование total_length (в некоторых случаях вы, вероятно, можете рассматривать это как категориальную переменную, но давайте не будем забегать вперед) и vowel-ratio, Например, вы можете в основном связать значения, которые вы видите в каждой функции, с одним из 5 значений на основе процентиля: "очень маленький", "маленький", "средний", "высокий", "очень высокий". Насколько я знаю, в sk-learn нет простого способа, но сделать это самостоятельно довольно просто. Единственное, что вы хотели бы изменить, это то, что вы хотели бы использовать MultinomialNB вместо GaussianNB потому что вы будете иметь дело с особенностями, которые будут лучше описаны многочленными распределениями, а не гауссовыми.

  2. Мы можем преобразовать категориальные функции в числовые для использования с GaussianNB, Лично я считаю, что это более интуитивный подход. По сути, при работе с текстом вам нужно выяснить, какую информацию вы хотите извлечь из текста и передать в классификатор. Мне кажется, что вы хотите извлечь количество разных двухбуквенных фамилий.

    Обычно я спрашиваю вас, есть ли у вас все фамилии в вашем наборе данных, но, поскольку каждая из них состоит всего из двух букв, мы можем просто сохранить все возможные двухбуквенные имена (включая символы Юникода с акцентными знаками) с минимальным влиянием по производительности. Это где-то вроде склеарна CountVectorizer может быть полезным. Предполагая, что у вас есть любая возможная комбинация двухбуквенных фамилий в ваших данных, вы можете просто напрямую использовать это, чтобы превратить строку в столбце twoLetter_lastname в N-мерный вектор, который записывает количество вхождений каждой уникальной фамилии в вашей строке., Затем просто объедините этот новый вектор с двумя другими вашими объектами в массив.

    В случае, если у вас нет всех возможных комбинаций из двух букв (включая акцентированные), вы должны рассмотреть возможность создания этого списка и передать его в качестве "словаря" для CountVectorizer. Это сделано для того, чтобы ваш классификатор знал, как обрабатывать все возможные фамилии. Это не конец света, если вы не обрабатываете все случаи, но любые новые невидимые двухбуквенные пары будут игнорироваться в этой схеме.

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

    Вы можете прочитать больше об общей предварительной обработке sklearn здесь, и больше о CountVectorizer и другие инструменты для извлечения текстовых функций, представленные здесь. Я ежедневно использую множество этих инструментов и рекомендую их для базовых задач извлечения текста. Есть также много обучающих программ и демонстраций, доступных онлайн. Вы можете также искать другие типы методов представления, такие как бинаризация и однократное кодирование. Есть много способов решить эту проблему, в основном это зависит от вашей конкретной проблемы / потребностей.


После того, как вы сможете превратить все свои данные в одну или другую форму, вы сможете использовать гауссовский или многочленный NB-классификатор. Что касается вашей ошибки относительно вектора 1D, вы напечатали df_Y, и это выглядело как

[[u'non-A']
 [u'A']
 [u'non-A']
 ..., 
 [u'A']
 [u'non-A']
 [u'non-A']]

По сути, он ожидает, что это будет плоский список, а не вектор-столбец (список одномерных списков). Просто измените его соответствующим образом, используя такие команды, как numpy.reshape() или numpy.ravel() (вероятно, более подходящим будет numpy.ravel (), учитывая, что вы имеете дело только с одним столбцом, как упоминалось в сообщении об ошибке).

Я не уверен на 100%, но я думаю, что scikit-learn.naive_bayes требует чисто числового векторного элемента вместо смеси текста и чисел. Похоже, что происходит сбой при попытке "разделить" строку Юникода длинным целым числом.

Я не могу помочь с поиском числовых представлений для текста, но этот учебник scikit-learn может стать хорошим началом.

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