JANATA-HACK ДЕНЬ НЕЗАВИСИМОСТИ ML HACKATHON

Постановка задачи

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

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

Обратите внимание, что исследовательская статья может иметь более одной темы. Тезисы и названия научных статей взяты из следующих 6 тем:

  1. Информатика
  2. Физика
  3. Математика
  4. Статистика
  5. Количественная биология
  6. Количественные финансы

Описание

Импорт библиотек

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
from sklearn.preprocessing import LabelEncoder
import nltk
nltk.download('punkt')
nltk.download('wordnet')
nltk.download('stopwords')
nltk.download('averaged_perceptron_tagger')
from nltk import sent_tokenize, word_tokenize
from nltk.stem.snowball import SnowballStemmer
from nltk.stem.wordnet import WordNetLemmatizer
from nltk.corpus import stopwords
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer, TfidfTransformer

Импорт набора данных

train = pd.read_csv('/kaggle/input/janatahack-independence-day-2020-ml-hackathon/train.csv')
test = pd.read_csv('/kaggle/input/janatahack-independence-day-2020-ml-hackathon/test.csv')
samp = pd.read_csv('/kaggle/input/janatahack-independence-day-2020-ml-hackathon/sample_submission_UVKGLZE.csv')

ПОМЕТОЧНЫЙ ПОДСЧЕТ

l = ['Computer Science', 'Physics', 'Mathematics', 'Statistics', 'Quantitative Biology', 'Quantitative Finance']
for col in l:
    print(col,':\n',train[col].value_counts())

dic = {'CS' :8594,'Phy' :6013,'Math' :5618,'Stats' :5206,'QB' :587,'QF' :249}

values = dic.values()
total = sum(values)
percent_values = [value * 100. / total for value in values]
print(percent_values)
[32.71785891041992, 22.891841474092967, 21.388053451098337, 19.819545437240645, 2.234743213918605, 0.9479575132295276]

Разделение на поезд и набор проверки

X = train.loc[:,['TITLE','ABSTRACT']]
y = train.loc[:,l]

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.16, random_state=42)
test = test.drop(['ID'],axis=1)
y_test.reset_index(drop=True,inplace=True)
X_test.reset_index(drop=True,inplace=True)
y1 = np.array(y_train)
y2 = np.array(y_test)

Очистка текста

X_train.replace('[^a-zA-Z]',' ', regex=True, inplace=True)
X_test.replace('[^a-zA-Z]',' ', regex=True, inplace=True)

test.replace('[^a-zA-Z]',' ', regex=True, inplace=True)
for index in X_train.columns:
    X_train[index] = X_train[index].str.lower()

for index in X_test.columns:
    X_test[index] = X_test[index].str.lower()

for index in test.columns:
    test[index] = test[index].str.lower()
X_train['ABSTRACT'] = X_train['ABSTRACT'].str.replace(r'\b\w\b', '').str.replace(r'\s+', ' ')
X_test['ABSTRACT'] = X_test['ABSTRACT'].str.replace(r'\b\w\b', '').str.replace(r'\s+', ' ')

test['ABSTRACT'] = test['ABSTRACT'].str.replace(r'\b\w\b', '').str.replace(r'\s+', ' ')
X_train = X_train.replace('\s+', ' ', regex=True)
X_test = X_test.replace('\s+', ' ', regex=True)

test = test.replace('\s+', ' ', regex=True)
stop_words = set(stopwords.words('english')) 
len(stop_words)
X_train['ABSTRACT'] = X_train['ABSTRACT'].apply(lambda x: ' '.join(term for term in x.split() if term not in stop_words))
X_test['ABSTRACT'] = X_test['ABSTRACT'].apply(lambda x: ' '.join(term for term in x.split() if term not in stop_words))

test['ABSTRACT'] = test['ABSTRACT'].apply(lambda x: ' '.join(term for term in x.split() if term not in stop_words))
X_train['combined'] = X_train['TITLE']+' '+X_train['ABSTRACT']
X_test['combined'] = X_test['TITLE']+' '+X_test['ABSTRACT']

test['combined'] = test['TITLE']+' '+test['ABSTRACT']
X_train = X_train.drop(['TITLE','ABSTRACT'],axis=1)
X_test = X_test.drop(['TITLE','ABSTRACT'],axis=1)

test = test.drop(['TITLE','ABSTRACT'],axis=1)
train_lines = []
for row in range(0,X_train.shape[0]):
    train_lines.append(' '.join(str(x) for x in X_train.iloc[row,:]))

test_lines = []
for row in range(0,X_test.shape[0]):
    test_lines.append(' '.join(str(x) for x in X_test.iloc[row,:]))

predtest_lines = []
for row in range(0,test.shape[0]):
    predtest_lines.append(' '.join(str(x) for x in test.iloc[row,:]))
X.replace('[^a-zA-Z]',' ', regex=True, inplace=True)
for index in X.columns:
    X[index] = X[index].str.lower()
X['ABSTRACT'] = X['ABSTRACT'].str.replace(r'\b\w\b', '').str.replace(r'\s+', ' ')
X = X.replace('\s+', ' ', regex=True)
X['ABSTRACT'] = X['ABSTRACT'].apply(lambda x: ' '.join(term for term in x.split() if term not in stop_words))
X['combined'] = X['TITLE']+' '+X['ABSTRACT']

Удаление заголовка и аннотации из набора данных

X = X.drop(['TITLE','ABSTRACT'],axis=1)
X_lines = []
for row in range(0,X.shape[0]):
    X_lines.append(' '.join(str(x) for x in X.iloc[row,:]))

Преобразование в векторы и последующее преобразование

countvector = CountVectorizer(ngram_range=(4,8),analyzer='char',lowercase=False,strip_accents='unicode')
X_train_cv = countvector.fit_transform(train_lines)
X_test_cv = countvector.transform(test_lines)
test_cv = countvector.transform(predtest_lines)
from sklearn.feature_extraction.text import TfidfVectorizer, TfidfTransformer

tfidfvector = TfidfTransformer(sublinear_tf=True,use_idf=True)
X_train_tf = tfidfvector.fit_transform(X_train_cv)
X_test_tf = tfidfvector.fit_transform(X_test_cv)
test_tf = tfidfvector.fit_transform(test_cv)
X_cv = countvector.transform(X_lines)
X_tf = tfidfvector.fit_transform(X_cv)

Многоканальный классификатор с линейным SVC

from sklearn.svm import LinearSVC
from sklearn.multioutput import MultiOutputClassifier
from sklearn.multiclass import OneVsRestClassifier

model = LinearSVC(class_weight='balanced',loss="hinge",fit_intercept=False)
models = MultiOutputClassifier(model)
models.fit(X_tf, y)
preds = models.predict(X_test_tf)
print(classification_report(y2,preds))
print(accuracy_score(y2,preds))

predssv = models.predict(test_tf)
test1 = pd.read_csv('/kaggle/input/janatahack-independence-day-2020-ml-hackathon/test.csv')
submit = pd.DataFrame({'ID': test1.ID, 'Computer Science': predssv[:,0],'Physics':predssv[:,1],'Mathematics':predssv[:,2],'Statistics':predssv[:,3],'Quantitative Biology':predssv[:,4],'Quantitative Finance':predssv[:,5]})
submit.to_csv('submission.csv', index=False)

Результаты

С многовыходным классификатором с линейным SVC мы получаем точность 90%, при этом все классы имеют хорошие оценки f1. Мы можем дополнительно настроить эту модель, настроив гиперпараметры, чтобы улучшить оценки.

Надеюсь, вам понравился анализ!

Ссылка на набор данных

https://www.kaggle.com/vin1234/janatahack-independence-day-2020-ml-hackathon

Ссылка на проект

https://colab.research.google.com/drive/174jR-jarRwSw2hnu1OyQ8pvkKT_RPM7e#scrollTo=5gkTGnXT3N2W