Я обучаю классификатора прогнозированию, который классифицирует текстовые запросы по отделам.У меня есть ~ 107 000 помеченных примеров из 22 несбалансированных классов с примерно следующим распределением:
- Класс 1: 10000
- Класс 2: 60000
- Класс 3: 7000
- Класс 4: 5000
- Класс 5: 3500
- Классы 6 и 7: 2000 образцов каждый
- Классы 7-15: 1500 образцов каждый
- Классы 16-22: 500 выборок каждый
Я проводил предварительную обработку данных, чтобы получить четное количество выборок (где каждый класс имеет от 5000 до 50 000 выборок).Какой вышеупомянутый классификатор и уравновешивая тренировочные данные, я могу получить с точностью до 98,5% на тестовых данных с 50-50 разделением общих тренировочных данных.Но когда поступают новые запросы и я загружаю классификатор, классификатор в лучшем случае достигает только 50-70% точности.Образец относительно стабилен, поэтому одни и те же запросы всегда направляются в один и тот же отдел, поэтому я очень удивлен, что точность составляет лишь 50-70%, особенно при такой высокой точности данных испытаний:
import logging
import os
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.externals import joblib
from sklearn.metrics import classification_report
logger = logging.getLogger(__name__)
def up_sample(data, labels, **kwargs):
label_counts = Counter(labels)
max_label = max(label_counts, key=label_counts.get)
max_label_count = kwargs.get('samples', label_counts[max_label])
output_text = []
output_labels = []
for label, count in label_counts.items():
label_text = [data_row for data_row, label_row in zip(data, labels) if label_row == label]
resampled_labels = [label] * max_label_count
resampled_text = resample(label_text, n_samples=max_label_count, random_state=0)
output_text = output_text + resampled_text
output_labels = output_labels + resampled_labels
return output_text, output_labels
clf = Pipeline(
steps=(('tfidf_vectorizer', TfidfVectorizer(stop_words='english')),
('clf', RandomForestClassifier(n_estimators=250, n_jobs=-1)))
)
resampled_data, resampled_labels = upsample(data, labels) # UPDATE: produces ~700,000 samples, which many duplicates
labels = label_encoder.fit_transform(labels)
X_train, X_test, y_train, y_test = train_test_split(data, labels, test_size=0.5, random_state=0) # UPDATE: many duplicates in both training and test data sets as a result of upsampling
clf.fit(X_train, y_train)
test_score = clf.score(X_test, y_test)
logger.debug('Test Score: %s', test_score) # 0.98-0.99%
cross_validation_results = cross_val_score(clf, data, labels)
logger.debug('Cross Validation results: %r', cross_validation_results) # [98.7, 99.1, 97.8]
y_test_predicted = clf.predict(X_test)
output_classification_report = classification_report(y_test, y_test_predicted, target_names=label_encoder.classes_)
logger.debug(output_classification_report) # 0.95-1.0 for precision and recall for all classes
clf_file_name = os.path.join(directory, clf_name)
joblib.dump(clf, clf_file_name)
label_encoder_file_name = os.path.join(directory, label_encoder_name)
joblib.dump(label_encoder, label_encoder_file_name)
# Later, in a different script
clf_file_name = os.path.join(directory, name)
clf = joblib.load(clf_file_name)
label_encoder_file_name = os.path.join(directory, name)
label_encoder = joblib.load(label_encoder_file_name)
predictions = clf.predict(new_data)
logger.debug(clf.score(new_labels, predictions)) # 50-70%
Кроме того, когда я переучиваю классификатор с помощью new_data и прогнозирую на основе new_data, это на 100% точно.Я знаю, что он будет намного выше, поскольку он уже видел пример, но я читал об ошибке «вне пакета» в случайных лесах, которая, как я понимаю, могла быть моей проблемой, но я недостаточно знаком с OOB, чтобы знать, какисправить это.Я не знаю, как действовать отсюда.Как мне решить эту проблему?
Я уже прочитал следующие вопросы / ресурсы для решения своей проблемы, прежде чем опубликовать свой собственный вопрос, но не стесняйтесь сообщить мне, если я что-то пропустил из них: