Как получить прогнозы Top 3 или Top N с помощью SGDClassifier sklearn

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
from sklearn import linear_model
arr=['dogs cats lions','apple pineapple orange','water fire earth air', 'sodium potassium calcium']
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(arr)
feature_names = vectorizer.get_feature_names()
Y = ['animals', 'fruits', 'elements','chemicals']
T=["eating apple roasted in fire and enjoying fresh air"]
test = vectorizer.transform(T)
clf = linear_model.SGDClassifier(loss='log')
clf.fit(X,Y)
x=clf.predict(test)
#prints: elements

В приведенном выше коде clf.predict() выводит только 1 лучший прогноз для выборки из списка X. Меня интересуют 3 лучших прогноза для конкретной выборки в списке X, я знаю, что функция predict_proba/predict_log_proba возвращает список всех вероятностей для каждой функции в список Y, но его необходимо отсортировать, а затем связать с объектами в списке Y, прежде чем получить 3 лучших результата. Есть ли прямой и эффективный способ?


person Pranay Mathur    schedule 08.09.2015    source источник
comment
@user1269942: Очень полезное дополнение! Однако я не совсем понял функцию переменной истины. Можете ли вы уточнить, пожалуйста?   -  person Statmonger    schedule 24.02.2019


Ответы (6)


Встроенной функции нет, а что не так с

probs = clf.predict_proba(test)
best_n = np.argsort(probs, axis=1)[-n:]

?

Как было предложено одним из комментариев, следует изменить [-n:] на [:,-n:]

probs = clf.predict_proba(test)
best_n = np.argsort(probs, axis=1)[:,-n:]
person Andreas Mueller    schedule 10.09.2015
comment
Нет имен, связанных с соответствующей вероятностью! - person Pranay Mathur; 11.09.2015
comment
clf.classes_ предоставляет их. - person Andreas Mueller; 13.09.2015
comment
Разве нарезка не должна быть best_n = np.argsort(probs, axis=1)[:, -n:] ? - person MCMZL; 03.08.2018
comment
Привет, @AndreasMueller, как бы ты сопоставил clf.classes_ с probs? Я новичок в Python и провел последние 90 минут, пытаясь понять, как сопоставить индексы классов с реальными классами... спасибо! - person sweetmusicality; 30.03.2019
comment
еще один вопрос: нарезка с помощью best_n дает 3-й лучший, 2-й лучший, затем 1-й лучший. как можно поменять порядок так, чтобы сначала было 1-е, 2-е, а потом 3-е? еще раз спасибо! - person sweetmusicality; 30.03.2019
comment
woohoo еще раз понял это! не стесняйтесь удалять эти комментарии, если они кажутся неуместными, но я думаю, что они могут помочь другим. best_n = np.argsort(-probs, axis = 1)[:, :3] - person sweetmusicality; 30.03.2019
comment
Кажется, я получаю правильные результаты, но правильно ли я нарезаю [:,-n:] вместо [-n:]? - person Hamman Samuel; 29.01.2020

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

#both preds and truths are same shape m by n (m is number of predictions and n is number of classes)
def top_n_accuracy(preds, truths, n):
    best_n = np.argsort(preds, axis=1)[:,-n:]
    ts = np.argmax(truths, axis=1)
    successes = 0
    for i in range(ts.shape[0]):
      if ts[i] in best_n[i,:]:
        successes += 1
    return float(successes)/ts.shape[0]

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

person user1269942    schedule 01.02.2018

Надеюсь, Андреас поможет с этим. predict_probs недоступен, когда loss='петля'. Чтобы получить высший класс n, когда loss = 'шарнир', выполните:

calibrated_clf = CalibratedClassifierCV(clfSDG, cv=3, method='sigmoid')
model = calibrated_clf.fit(train.data, train.label)

probs = model.predict_proba(test_data)
sorted( zip( calibrated_clf.classes_, probs[0] ), key=lambda x:x[1] )[-n:]

Не уверен, что clfSDG.predict и linear_clf.predict всегда будут предсказывать один и тот же класс.

person valearner    schedule 09.08.2017
comment
Учитывая, что потеря журнала для SGDClassifier составляет OvR, вы также можете просто ранжировать на decision_function, и это никоим образом не будет хуже. Использование CalibratedClassifierCV, вероятно, лучше, но ортогонально вопросу. Я бы использовал LogisticRegression (multiclass = 'multinomial'). - person Andreas Mueller; 09.08.2017

argsort дает результаты в порядке возрастания, если вы хотите избавить себя от необычных циклов или путаницы, вы можете использовать простой трюк.

probs = clf.predict_proba(test)
best_n = np.argsort(-probs, axis=1)[:, :n]

Отрицание вероятностей превратит наименьшую в наибольшую, и, следовательно, вы можете взять первые n результатов в порядке убывания.

person Gaurav Singhal    schedule 30.06.2020

Как @FredFoo описано в Как мне получить индексы N максимальных значений в массиве NumPy? более быстрым методом было бы использование argpartition.

В более новых версиях NumPy (1.8 и выше) для этого есть функция argpartition. Чтобы получить индексы четырех самых больших элементов, выполните

>>> a = np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
>>> a array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
>>> ind = np.argpartition(a, -4)[-4:]
>>> ind array([1, 5, 8, 0])
>>> a[ind] array([4, 9, 6, 9])

В отличие от argsort, эта функция в худшем случае работает за линейное время, но возвращаемые индексы не сортируются, как видно из результата вычисления a[ind]. Если вам это тоже нужно, отсортируйте их потом:

>>> ind[np.argsort(a[ind])] array([1, 8, 5, 0]) 

Получение top-k элементов в отсортированном порядке занимает O(n + k log k) времени.

person Anthony Romm    schedule 20.08.2020

Я написал функцию, которая выводит кадр данных с n лучшими прогнозами и их вероятностями и связывает их с именами классов. Надеюсь, это полезно!

def return_top_n_pred_prob_df(n, model, X_test, column_name):
  predictions = model.predict_proba(X_test)
  preds_idx = np.argsort(-predictions) 
  classes = pd.DataFrame(model.classes_, columns=['class_name'])
  classes.reset_index(inplace=True)
  top_n_preds = pd.DataFrame()
  for i in range(n):
        top_n_preds[column_name + '_prediction_{}_num'.format(i)] =     [preds_idx[doc][i] for doc in range(len(X_test))]
    top_n_preds[column_name + '_prediction_{}_probability'.format(i)] = [predictions[doc][preds_idx[doc][i]] for doc in range(len(X_test))]
    top_n_preds = top_n_preds.merge(classes, how='left', left_on= column_name + '_prediction_{}_num'.format(i), right_on='index')
    top_n_preds = top_n_preds.rename(columns={'class_name': column_name + '_prediction_{}'.format(i)})
    try: top_n_preds.drop(columns=['index', column_name + '_prediction_{}_num'.format(i)], inplace=True) 
    except: pass
  return top_n_preds
person msheridan    schedule 09.03.2021