Как я создал простой классификатор предметов науки о данных для пометки базы данных грантов Фонда Рокфеллера.

Этот пост, написанный Дастином Маршаллом, основан на многих темах, представленных в интервью между редакторами Towards Data Science и Фондом Рокфеллера из прошлогодней серии В центре внимания сообщества.

Команда Data Science в Фонде Рокфеллера

Прошедшее лето я провел в составе группы по науке о данных Фонда Рокфеллера, которая является частью их Команды по инновациям. Одной из задач команды в этом году был мониторинг всех инновационных способов использования искусственного интеллекта в социальном секторе на благо общества.Эта работа требует от команды изучения методов обработки данных и опыта в сети грантополучателей RF.

Как их летний сотрудник по науке о данных, мне было поручено создать простую, но эффективную модель классификации, чтобы определить, связан ли грант с наукой о данных. Эта модель будет применять бинарный тег — связан или не связан с наукой о данных — к грантам фонда. Знание того, какие организации используют методы обработки данных, поможет нам определить возможности для будущих приложений науки о данных. Я надеюсь, что представленный ниже процесс (и код) будет поучительным для начинающих пользователей данных, которые хотят адаптировать его для нужд своего проекта.

Построение модели классификации науки о данных

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

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

В контролируемом машинном обучении, чтобы модель могла делать прогнозы на неизвестных данных, ее необходимо обучать на известных данных. По этой причине после извлечения 1 000 последних предложений, представленных в Фонд , примерно 100 из них были помечены вручную как связанные с наукой о данных. Критерием для этого было то, что предложение должно было использовать грантовые деньги для разработки или улучшения информационного продукта.

# Convert csv with data science proposals text to pandas dataframe & add classification label
data_science_proposals = pd.read_csv("DataScienceProposals.csv", header=None)
data_science_proposals.columns = ["raw_text"]
data_science_proposals["label"] = np.ones(len(data_science_proposals), dtype=np.int32)
# Convert csv with other proposals text to pandas dataframe & add classification label
other_proposals = pd.read_csv("OtherProposals.csv", header=None)
other_proposals.columns = ["raw_text"]
other_proposals["label"] = np.zeros(len(other_proposals), dtype=np.int32)

Чтобы модели НЛП работали наилучшим образом, важно, чтобы данные были предварительно обработаны, удаляя ненужные и противоречивые детали. Для этой модели используются библиотека анализа данных Python Pandas и математическая библиотека NumPy. » использовались для импорта и подготовки данных. Затем была использована библиотека Natural Language Toolkit (NLKT) для предварительной обработки данных путем удаления специальных символов и знаков препинания. Затем, используя тот же пакет NLKT, в процессе, называемом лемматизация, различные формы одного и того же слова были сведены к его корневому слову.

# Create function to pre-process text to improve model performance
def text_preprocessing(text):
    text = text.lower()
    text = re.sub('[^a-zA-Z]', ' ', text)
    text = text.split() 
    text = [WordNetLemmatizer().lemmatize(word) for word in text if 
        not word in set(stopwords.words('english'))]
    text = ' '.join(text)
    return text

Чтобы модель можно было обучить на данных, они должны быть переданы через модель таким образом, чтобы их можно было понять. Для этого модель включает конвейер, который сначала преобразует каждое уникальное слово в числа в зависимости от того, как часто это слово появляется в документе и как часто это слово появляется в наборе документов, помеченных как связанные с наукой о данных. Этот процесс называется векторизацией текста Term Frequency-Inverse Document Frequency (TF-IDF) и может быть выполнен просто с помощью пакета машинного обучения Python Scikit-learn (sklearn). Чтобы улучшить способность модели к дальнейшему пониманию данных, конвейер снова использует sklearn для выполнения Singular Value Decomposition (SVD) для векторов, что еще больше удаляет избыточность в данных, затем стандартизирует данные, преобразуя числа так, чтобы среднее значение равно 0, а стандартное отклонение равно 1. После обработки данные были разделены на наборы для обучения и тестирования.

# Build pipeline to transform and process text
model = Pipeline(steps=[
    ("tfidf", TfidfVectorizer(ngram_range=(2,4), min_df=5, 
        max_df=0.5, sublinear_tf=True, stop_words="english")), 
    ("svd", TruncatedSVD(n_components=64, n_iter=10, 
        random_state=1)),
    ("scaler", StandardScaler()))

Поскольку существует несколько моделей классификации, которые можно использовать, и в каждой модели есть гиперпараметры, которые можно настроить для повышения производительности, важно отложить данные в обучающем наборе для проверки и проверки вашего выбора . Для этой модели обучающий набор был снова разделен, чтобы включить дополнительный набор для проверки, а затем оценен с использованием различных моделей классификации из библиотеки sklearn с классификатором Машина опорных векторов (SVM), имеющим наивысший показатель производительности. Затем гиперпараметры модели были настроены с использованием того же подхода.

# Iterate through classifiers, building pipeline that transforms text and passes it through classifier
for name, classifier in [
          ('LogReg', LogisticRegression()), 
          ('RF', RandomForestClassifier()),
          ('KNN', KNeighborsClassifier()),
          ('SVM', SVC(probability=True)), 
          ('GNB', GaussianNB()),
          ('XGB', XGBClassifier())]:
    model = Pipeline(steps=[
        ("tfidf", TfidfVectorizer(ngram_range=(2,4), min_df=5, 
            max_df=0.5, sublinear_tf=True, stop_words="english")),
        ("svd", TruncatedSVD(n_components=64, n_iter=10, 
            random_state=1)),
        ("scaler", StandardScaler()),
        (name, classifier)])

Принятие решения о том, как оценивать производительность модели классификации, зависит от того, где потребности варианта использования ложатся на компромисс между точностью и полнотой. В этом случае очень важно, чтобы модель помечала все предложения по науке о данных как связанные с наукой о данных, даже если есть некоторые помеченные предложения, которые таковыми не являются. Это пример модели, ориентированной на припоминание, которая требует меры оценки, учитывающей это. По этой причине модель оценивается с использованием показателя F2-Score, который пропорционально сочетает показатели точности и полноты, а также переоценивает полноту.

# Evaluate average model performance across 10 random states (to account for the small sample size)
f2_scores_byrandomstate = []
for n in range(1,11):
    # split data into training, validation, and testing sets
    X = data["processed_text"].values
    y = data["label"].values
    X_train, X_test, y_train, y_test = train_test_split(X, y, 
        test_size=0.20, random_state=n, shuffle=True, stratify=y)
    train_X, validate_X, train_y, validate_y =  
        train_test_split(X_train, y_train, test_size=0.25, 
        random_state=n, shuffle=True, stratify=y_train)
    # fit model on the training set
    model.fit(train_X, train_y)
    # find max F2-Score measure for the model
    y_score = model.predict_proba(validate_X)[:, 1]
    precision, recall, thresholds = 
        precision_recall_curve(validate_y, y_score)
    f2_score = (5 * recall * precision) / (4 * recall + precision) + 
        1e-10
    f2_scores_byrandomstate.append(np.max(f2_score))
average_model_performance = np.average(f2_scores_byrandomstate)

После всей предварительной обработки текста, векторизации, выбора модели и настройки гиперпараметров самая эффективная модель получила F2-Score 0,828. Любая оценка выше 0,7 считается выше среднего, но оценка выше 0,9 была бы идеальной.

Полный код этой модели можно найти здесь.

Применение модели к корпусу предложений Фонда Рокфеллера

После обучения модели на самых последних 1 тыс. предложений, поданных в Фонд Рокфеллера, для поиска приложений, связанных с наукой о данных, теперь мы можем включить ее на оставшихся 4 тыс.+ предложений, хранящихся в нашей базе данных грантов, а также на любых будущих представленных предложениях. Взамен мы получаем предсказанные классификации по всем предложениям, поданным в фонд и продвигающимся вперед. Это поможет Фонду Рокфеллера упростить процесс идентификации получателей грантов с использованием методов обработки данных.

# Plot predicted data science proposals across time
additional_proposals = additional_proposals.groupby("year").sum()
plt.figure(figsize =(20, 10))
plt.bar(additional_proposals.index.values, 
    additional_proposals["predicted_label"])
plt.xlabel("Year", fontsize = 15)
plt.ylabel("Number of Predicted Data Science Proposals", fontsize = 
    15)
plt.title("Number of Predicted Data Science Proposals by Year", 
    fontweight ='bold', fontsize = 20)
plt.show()

Гранты по науке о данных в Фонде Рокфеллера

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

В завершение я выделил нескольких выдающихся грантополучателей из группы инноваций за последние годы, которые берут методы и модели из науки о данных — не слишком отличающиеся от описанных выше — и используют их для инноваций в решениях долгосрочных задач. постоянные проблемы, стоящие перед сообществами по всему миру.

  • DataKind: с 2017 года Фонд Рокфеллера выделил более 1 миллиона долларов США некоммерческой организации DataKind, базирующейся в США. Этот постоянный грант был использован для поддержки разнообразной работы организации с использованием искусственного интеллекта и прогнозной аналитики для улучшения жизни во всем мире и в целом для ее миссии по объединению науки о данных и некоммерческих сообществ для большего социального воздействия. Чтобы узнать больше об их последнем гранте, см. этот пост.
  • Data.org: с 2021 года Фонд Рокфеллера выделил более 10 миллионов долларов США американской некоммерческой организации Data.org для поддержки их усилий по созданию области науки о данных для социальное воздействие и установить высокоэффективные варианты использования. Чтобы узнать больше об их удивительной работе, см. этот пост.
  • AtlasAI:В прошлом месяце Фонд Рокфеллера предоставил грант в размере 1,8 миллиона долларов США американской B-Corporation AtlasAI с целью помочь им создать следующее поколение человека и Экономический атлас, инструмент науки о данных для измерения бедности и моделирования прогресса в области развития. Чтобы узнать больше об этом гранте, см. этот пост.