newsgroups = datasets.fetch_20newsgroups(
                    subset='all', 
                    categories=['alt.atheism', 'sci.space']
             )

"""
Explanation: 1. Для начала вам потребуется загрузить данные. В этом задании мы воспользуемся одним из датасетов, доступных в scikit-learn'е — 20 newsgroups. Для этого нужно воспользоваться модулем datasets:
End of explanation
"""


X = newsgroups.data
y = newsgroups.target
print("targets: ", y)
print("target_names: ", newsgroups.target_names)

"""
Explanation: 2. После выполнения этого кода массив с текстами будет находиться в поле newsgroups.data, номер класса — в поле newsgroups.target.
End of explanation
"""


print("Extracting features from the training data using vectorizer")
vectorizer = TfidfVectorizer()
X_train = vectorizer.fit_transform(X)
print("n_samples: %d, n_features: %d" % X_train.shape)

"""
Explanation: 3. Одна из сложностей работы с текстовыми данными состоит в том, что для них нужно построить числовое представление. Одним из способов нахождения такого представления является вычисление TF-IDF. В Scikit-Learn это реализовано в классе sklearn.feature_extraction.text.TfidfVectorizer. Преобразование обучающей выборки нужно делать с помощью функции fit_transform, тестовой — с помощью transform.
End of explanation
"""


# mapping from integer feature name to original token string
feature_names = np.asarray(vectorizer.get_feature_names())
feature_names

"""
Explanation: 4. Реализация SVM-классификатора находится в классе sklearn.svm.SVC. Веса каждого признака у обученного классификатора хранятся в поле coef_. Чтобы понять, какому слову соответствует i-й признак, можно воспользоваться методом get_feature_names() у TfidfVectorizer:
End of explanation
"""


grid = {'C': np.power(10.0, np.arange(-5, 6))}
cv = KFold(n_splits=5, shuffle=True, random_state=241)
clf = SVC(kernel='linear', random_state=241)
gs = GridSearchCV(clf, grid, scoring='accuracy', cv=cv)
gs.fit(X_train, y)

"""
Explanation: 5. Подбор параметров удобно делать с помощью класса sklearn.grid_search.GridSearchCV. Первым аргументом в GridSearchCV передается классификатор, для которого будут подбираться значения параметров, вторым — словарь (dict), задающий сетку параметров для перебора.
End of explanation
"""


df = pd.DataFrame.from_dict(gs.cv_results_)
df.head()
df_with_best_score = df[df['mean_test_score'] == (df['mean_test_score'].max())]
best_C = df_with_best_score['param_C'].max()
best_C

"""
Explanation: 6. После того, как перебор окончен, можно проанализировать значения качества для всех значений параметров и выбрать наилучший вариант:
End of explanation
"""


clf.set_params(C = best_C).fit(X_train, y)

"""
Explanation: 7. Обучите SVM по всей выборке с оптимальным параметром C, найденным на предыдущем шаге.
End of explanation
"""


absolute_data = abs(clf.coef_.toarray().reshape(-1)) # by absolute

absolute_data_sorted_desc = sorted(absolute_data, reverse=True)
weight_indexes = []
for weight in absolute_data_sorted_desc[:10]:
    weight_indexes.append(absolute_data.tolist().index(weight))   
        
words = [vectorizer.get_feature_names()[index] for index in weight_indexes]

print('%s' % (" ".join(sorted(words))))

"""
Explanation: 8. Найдите 10 слов с наибольшим абсолютным значением веса (веса хранятся в поле coef_ у svm.SVC). Они являются ответом на это задание. Укажите эти слова через запятую или пробел, в нижнем регистре, в лексикографическом порядке.
End of explanation
"""


