Olivia Brown
Olivia Brown

Reputation: 632

Trouble implementing Bernoulli Naive Bayes Classifier

I am trying to implement a Bernoulli Naive Bayes Classifier from scikit-learn library for text classification. But I am stuck with this error

ValueError: Expected 2D array, got 1D array instead:

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.

Error in detail

Traceback (most recent call last):
  File "BNB.py", line 27, in <module>
    clf.fit(train_data, train_labels)
  File "/home/atinesh/.local/lib/python3.6/site-packages/sklearn/naive_bayes.py", line 579, in fit
    X, y = check_X_y(X, y, 'csr')
  File "/home/atinesh/.local/lib/python3.6/site-packages/sklearn/utils/validation.py", line 573, in check_X_y
    ensure_min_features, warn_on_dtype, estimator)
  File "/home/atinesh/.local/lib/python3.6/site-packages/sklearn/utils/validation.py", line 441, in check_array
    "if it contains a single sample.".format(array))
ValueError: Expected 2D array, got 1D array instead:
array=['Apple' 'Banana' 'Cherry' 'Grape' 'Guava' 'Lemon' 'Mangos' 'Orange'
 'Strawberry' 'Watermelon' 'Potato' 'Spinach' 'Carrot' 'Onion' 'Cabbage'
 'Barccoli' 'Tomatoe' 'Pea' 'Cucumber' 'Eggplant'].
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.

"BNB.py"

from sklearn.naive_bayes import BernoulliNB

dataPos = ['Apple', 'Banana', 'Cherry', 'Grape', 'Guava', 'Lemon', 'Mangos',
            'Orange', 'Strawberry', 'Watermelon']

dataNeg = ['Potato', 'Spinach', 'Carrot', 'Onion', 'Cabbage', 'Barccoli', 
            'Tomatoe', 'Pea', 'Cucumber', 'Eggplant']

def get_data():
    examples = []
    labels   = []

    for item in dataPos:
        examples.append(item)
        labels.append('positive')

    for item in dataNeg:
        examples.append(item)
        labels.append('negative')

    return examples, labels

train_data, train_labels = get_data()

# Train
clf = BernoulliNB()
clf.fit(train_data, train_labels)

# Predict
print(clf.predict('Apple Banana'))
print(clf.predict_proba('Apple Banana'))

Upvotes: 0

Views: 840

Answers (2)

Ashoka Lella
Ashoka Lella

Reputation: 6729

I would recommend use the LabelBinarizer in sklearn

from sklearn.naive_bayes import BernoulliNB
import numpy as np
from sklearn import preprocessing

dataPos = ['Apple', 'Banana', 'Cherry', 'Grape', 'Guava', 'Lemon', 'Mangos',
                       'Orange', 'Strawberry', 'Watermelon']

dataNeg = ['Potato', 'Spinach', 'Carrot', 'Onion', 'Cabbage', 'Barccoli',
                       'Tomatoe', 'Pea', 'Cucumber', 'Eggplant']

Y=[0]*10+[1]*10
Y=np.array(Y)

lb = preprocessing.LabelBinarizer()
X = lb.fit_transform(dataPos+dataNeg)
clf = BernoulliNB()
clf.fit(X, Y)

test_sample = lb.transform([['Apple'],['Banana'],['Spinach']])
print clf.predict(test_sample)

Your code errors out because when doing clf.fit(X,Y), X needs to be 2d array. Each row corresponding to a feature vector.

Upvotes: 3

domochevski
domochevski

Reputation: 553

If you pass simple python lists to scikit_learn, it will be interpreted as an array of shape (n, ). What you might want to do is convert your lists of both examples and labels into numpy array and reshape/resize them into line vectors with a shape of (n, 1). For example:

import numpy as np

examples = np.array(['Apple', 'Banana', 'Cherry', 'Grape', 'Guava', 'Lemon', 'Mangos','Orange', 'Strawberry', 'Watermelon'])
examples.shape  # returns (10, ), a 1D-array
examples.resize((10,1))
examples.shape  # returns (10, 1), which is a 2-D array

Or for a more simple solution, you could simply provide the fit method with:

clf.fit([train_data], [train_labels])

But since you already have a dedicated method to format the data why not use numpy in there and return lists with the correct dimensions.

Hope this helps in your endeavor.

Upvotes: 0

Related Questions