Sklearn, randomforest dlaczego nie przyjmuje danych?

0

Witam,
robie projekt związany z RandomForestClassificator chciałbym użyć danych z mojego pliku csv. Na moje nieszczęście mój dataset ma dużo zmiennych tekstowych. Pomyślałem zatem, że zamienię je na zmienne liczbowe. Oczywiście robię tak i po uruchomieniu wyskakuje taki błąd:

C:/Users/bitel/PycharmProjects/TensorFlow/venv/RandomForest.py:30: 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().
  forest.fit(X_train,y_train)
Traceback (most recent call last):
  File "C:/Users/bitel/PycharmProjects/TensorFlow/venv/RandomForest.py", line 30, in <module>
    forest.fit(X_train,y_train)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\sklearn\ensemble\forest.py", line 276, in fit
    y, expanded_class_weight = self._validate_y_class_weight(y)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\sklearn\ensemble\forest.py", line 476, in _validate_y_class_weight
    check_classification_targets(y)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\sklearn\utils\multiclass.py", line 171, in check_classification_targets
    raise ValueError("Unknown label type: %r" % y_type)
ValueError: Unknown label type: 'continuous'

Co muszę zrobić, aby rozwiązać ten błąd?
Kod:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import pandas as pd
import numpy as np

chocolate = pd.read_csv("C:\choco.csv", delimiter=',')
print(chocolate.head())
#enc = preprocessing.OneHotEncoder
#enc.fit(chocolate[0])
data_random = chocolate.sample(frac=1)

keep_col = ['Company', 'Cocoa Percent', 'Company Location', 'Broad Bean Origin']
rating_col = ['Rating']

data_keep = data_random[keep_col]
ratings = data_random[rating_col]

print(ratings)

list_ratings = np.array(ratings).tolist()

print(list_ratings)
data_dummies = pd.get_dummies(data_keep)

print(data_dummies)

X_train, X_test, y_train, y_test = train_test_split(data_dummies,list_ratings, random_state=0)
forest = RandomForestClassifier(n_estimators=100,random_state=0)
forest.fit(X_train,y_train)

forest.score(X_train,y_train)
0

Spróbuj użyć LabelEncoder:

from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
chocolade_cat = chocolade[<cont category>]
chocolade_cat_encoded = encoder.fit_transform(chocolade_cat)
chocolade_cat_encoded
0

Robisz to inaczej niż na przykładzie, encoder.fit_transform bierze atrybut tekstowy, jako kolumnę pandas.

0

Ok, działa !!! Teraz wyskakuje tylko taki błąd:

C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\sklearn\preprocessing\label.py:235: 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)

Oto kod, mam nadzieję, że o to chodziło:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import pandas as pd
import numpy as np

chocolate = pd.read_csv("C:\choco.csv", delimiter=',')
print(chocolate.head())
#data_random = chocolate.sample(frac=1)

keep_col = ['Company', 'Cocoa Percent', 'Company Location', 'Broad Bean Origin']
rating_col = ['Rating']

data_keep = chocolate[keep_col]
ratings = chocolate[rating_col]

encoder = preprocessing.LabelEncoder()
ratings_encoded = encoder.fit_transform(ratings)

data_dummies = pd.get_dummies(data_keep)

X_train, X_test, y_train, y_test = train_test_split(data_dummies,ratings_encoded, random_state=0)
forest = RandomForestClassifier(n_estimators=100,random_state=0)
forest.fit(X_train,y_train)

print(forest.score(X_train,y_train))
print(forest.score(X_test,y_test))

Co ciekawe, mam już wyniki.
Dla danych treningowych:

print(forest.score(X_train,y_train))

dostaje wynik: 0.9190193164933135
a dla danych testowych:

print(forest.score(X_test,y_test))

dostaje wynik tylko: 0.2071269487750557

Jaka może być przyczyna? Czy to overfitting? Jak temu zaradzić? Mój csv ma ok 1800 wierszy. Zmienić liczbę drzew?

0

Overfitting widać gołym okiem, Zmniejsz liczbę drzew, to na pewno. Spróbuj może RandomForrestRegressor , z m = RandomForrestRegressor(n_jobs=-1)

0

Zmniejszyłem do 20, niestety wyniki nie są jakieś zadowalające. Nadal występuje overfitting. Jak można temu zaradzić?

X_train, X_test, y_train, y_test = train_test_split(data_dummies, ratings_encoded, random_state=0)

forest = RandomForestClassifier(n_estimators=20, random_state=0)
m = RandomForestRegressor(n_estimators=20, n_jobs=-1, random_state=0)
forest.fit(X_train, np.ravel(y_train))
m.fit(X_train,np.ravel(y_train))

print(forest.score(X_train, y_train))
print(forest.score(X_test, y_test))

print(m.score(X_train, y_train))
print(m.score(X_test, y_test))

Wyniki:

0.9093610698365527
0.18485523385300667
0.8205033497796521
0.07433200155457109

Próbuję eksperymentować z max_feature, max_depth oraz min_samples_leaf; ale ciężko idzie

0

Ok, udało się. Poczyniłem duże postępy. Dla drzew klasyfikujacych zamieniłem kolumnę ratings w bardziej przyjazną formę. Uznałem, że las ma sprawdzać jakie warunki wpływają na to, że dana tabliczka czekolady uzyskuje ranking większy niż "3.7" Z tego też powodu zamieniłem wartości >= 3.7 na "1" a <=3.7 na "0" Sieć dostała jasny obraz co jest poprawne a co nie. Dla drzew regresji zostawiłem starą formę.
Ratings przyjmuje oceny w skali 1-5, lecz z histogramu wynika, że najwięcej informacji jest w zakresie 2.5-4.0 (usunięcie wartości >4.0 i <2.5 wcale nie polepszyło wyników)
Pytanie brzmi, jak zoptymalizować to jeszcze lepiej :-) ? No i czy da się na tym datasecie (1800 wierszy)

Classification forest:
0.9739970282317979
0.8129175946547884 

Regression forest:
0.7604010783215122
-0.0372907695057485

Kod:

from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

chocolate = pd.read_csv("C:\choco.csv", delimiter=',')
print(chocolate.head())
data_random = chocolate.sample(frac=1)

keep_col = ['Company', 'Cocoa Percent', 'Company Location', 'Broad Bean Origin']
rating_col = ['Rating']

data_keep = data_random[keep_col]
ratings = data_random[rating_col]
regress_ratings = ratings

for index, row in ratings.iterrows():
    #if(row['Rating']>4 or row['Rating']<2.5):
        #ratings.drop(index)
    if(row['Rating']>3.7):
        row['Rating']=1.0
    else:
        row['Rating']=0.0

encoder = preprocessing.LabelEncoder()
ratings_encoded = encoder.fit_transform(ratings)
regress_ratings_encoded = encoder.fit_transform(regress_ratings)

data_dummies = pd.get_dummies(data_keep)

X_train, X_test, y_train, y_test = train_test_split(data_dummies, ratings_encoded, random_state=0)
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(data_dummies, regress_ratings_encoded, random_state=0)

forest = RandomForestClassifier(n_estimators=100, random_state=0)
m = RandomForestRegressor(n_estimators=20, n_jobs=-1, random_state=0)
forest.fit(X_train, np.ravel(y_train))
m.fit(X_train_reg,np.ravel(y_train_reg))

print("Classification forest:")
print(forest.score(X_train, y_train))
print(forest.score(X_test, y_test),"\n")

print("Regression forest:")
print(m.score(X_train_reg, y_train_reg))
print(m.score(X_test_reg, y_test_reg))

pos = np.arange(len(keep_col))

plt.barh(pos,forest.feature_importances_,align='center')
plt.xticks(pos,keep_col)
plt.xlabel('Feature Importance')
plt.ylabel('Feature')
plt.show()

Tak btw funkcja barh powoduje taki dziwny błąd, którego do końca nie rozumiem, bo pos jest 4 elementowy a forest.feature_importances też ma 4 kolumny. (robię tak jak jest we wszystkich tutorialach), lecz do tego założę chyba osobny temat.

Traceback (most recent call last):
  File "C:/Users/bitel/PycharmProjects/TensorFlow/venv/RandomForest.py", line 53, in <module>
    plt.barh(pos,forest.feature_importances_,align='center')
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\matplotlib\pyplot.py", line 2473, in barh
    y, width, height=height, left=left, align=align, **kwargs)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\matplotlib\axes\_axes.py", line 2463, in barh
    align=align, **kwargs)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\matplotlib\__init__.py", line 1810, in inner
    return func(ax, *args, **kwargs)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\matplotlib\axes\_axes.py", line 2251, in bar
    np.atleast_1d(x), height, width, y, linewidth)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\numpy\lib\stride_tricks.py", line 252, in broadcast_arrays
    shape = _broadcast_shape(*args)
  File "C:\Users\bitel\PycharmProjects\TensorFlow\venv\lib\site-packages\numpy\lib\stride_tricks.py", line 187, in _broadcast_shape
    b = np.broadcast(*args[:32])
ValueError: shape mismatch: objects cannot be broadcast to a single shape
0

"Pytanie brzmi, jak zoptymalizować to jeszcze lepiej" Rzuć okiem tutaj: https://github.com/fastai/fastai/tree/master/courses/ml1 , oraz: https://forums.fast.ai/t/anot[...]eos/6826?source_topic_id=9398

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0