Категоризация - агрегация данных с использованием iPython - PullRequest
0 голосов
/ 03 марта 2020

У меня 196 описаний преступлений, присвоенных примерно 1700 записям в CSV-файле, которые мне нужно сгруппировать по 20 категориям, чтобы я мог сделать их значимые символы на карте. Я присвоил свои собственные категории 80 записям, надеясь, что этого будет достаточно для обучения простой модели классификации. Я попытался запустить данные с помощью некоторых методов numpy и sklearn из этого поста: https://towardsdatascience.com/multi-class-text-classification-with-scikit-learn-12f1e60e0a9f

, но результаты не были значимыми (я выше моего понимания!). Вот ссылка на репо git, в котором есть i Python и связанные csv-файлы: https://github.com/jshaunobryan/Data_Categorization

Я выполнил шаги i Python с версией CSV-файлы со всеми пустыми значениями, удаленными для агрегированных описаний. CSV-файл CrimeCodeAgg содержит все строки данных перед удалением значений AggregatedDes c Null. Код в записной книжке i Python привел к нескольким ошибкам индекса, но, что более важно, я думаю, что я просто ошибаюсь.

Для тех из вас, у кого нет доступа к github, приведен код из записной книжки i Python:

import pandas as pd
df = pd.read_csv(r"C:\CrimeCodeAgg_NoNull.csv")
df

from io import StringIO

col = ["AggregatedDesc","CrimeDescription"]
df = df[col]
df = df[pd.notnull(df['CrimeDescription'])]

df.columns = ["AggregatedDesc","CrimeDescription"]

df['category_id'] = df["AggregatedDesc"].factorize()[0]

category_id_df = df[['AggregatedDesc', 'category_id']].drop_duplicates().sort_values('category_id')
category_to_id = dict(category_id_df.values)
id_to_category = dict(category_id_df[['category_id', 'AggregatedDesc']].values)

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,6))
df.groupby('AggregatedDesc').CrimeDescription.count().plot.bar(ylim=0)
plt.show();

import sklearn
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(sublinear_tf=True, min_df=5, norm='l2', encoding='latin-1', ngram_range=(1, 2), stop_words='english')
features = tfidf.fit_transform(df.CrimeDescription).toarray()
labels = df.category_id
features.shape

from sklearn.feature_selection import chi2
import numpy as np
N = 2
for AggregatedDesc, category_id in sorted(category_to_id.items()):
  features_chi2 = chi2(features, labels == category_id)
  indices = np.argsort(features_chi2[0])
  feature_names = np.array(tfidf.get_feature_names())[indices]
  unigrams = [v for v in feature_names if len(v.split(' ')) == 1]
  bigrams = [v for v in feature_names if len(v.split(' ')) == 2]
  print("# '{}':".format( AggregatedDesc))
  print("  . Most correlated unigrams:\n. {}".format('\n. '.join(unigrams[-N:])))
  print("  . Most correlated bigrams:\n. {}".format('\n. '.join(bigrams[-N:])))

from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
X_train, X_test, y_train, y_test = train_test_split(df['CrimeDescription'], df['AggregatedDesc'], random_state = 0)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(X_train)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
clf = MultinomialNB().fit(X_train_tfidf, y_train)

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVC

from sklearn.model_selection import cross_val_score
models = [
    RandomForestClassifier(n_estimators=200, max_depth=3, random_state=0),
    LinearSVC(),
    MultinomialNB(),
    LogisticRegression(random_state=0),
]
CV = 5
cv_df = pd.DataFrame(index=range(CV * len(models)))
entries = []
for model in models:
  model_name = model.__class__.__name__
  accuracies = cross_val_score(model, features, labels, scoring='accuracy', cv=CV)
  for fold_idx, accuracy in enumerate(accuracies):
    entries.append((model_name, fold_idx, accuracy))
cv_df = pd.DataFrame(entries, columns=['model_name', 'fold_idx', 'accuracy'])
import seaborn as sns
sns.boxplot(x='model_name', y='accuracy', data=cv_df)
sns.stripplot(x='model_name', y='accuracy', data=cv_df, 
              size=8, jitter=True, edgecolor="gray", linewidth=2)
plt.show()

cv_df.groupby('model_name').accuracy.mean()

model = LinearSVC()
X_train, X_test, y_train, y_test, indices_train, indices_test = train_test_split(features, labels, df.index, test_size=0.33, random_state=0)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
from sklearn.metrics import confusion_matrix
conf_mat = confusion_matrix(y_test, y_pred)
fig, ax = plt.subplots(figsize=(10,10))
sns.heatmap(conf_mat, annot=True, fmt='d',
            xticklabels=category_id_df.AggregatedDesc.values, yticklabels=category_id_df.AggregatedDesc.values)
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()

from IPython.display import display
for predicted in category_id_df.category_id:
  for actual in category_id_df.category_id:
    if predicted != actual and conf_mat[actual, predicted] >= 100:
      print("'{}' predicted as '{}' : {} examples.".format(id_to_category[actual], id_to_category[predicted], conf_mat[actual, predicted]))
      display(df.loc[indices_test[(y_test == actual) & (y_pred == predicted)]][['AggregatedDesc', 'CrimeDescription']])
      print('')

model.fit(features, labels)
N = 2
for Product, category_id in sorted(category_to_id.items()):
  indices = np.argsort(model.coef_[category_id])
  feature_names = np.array(tfidf.get_feature_names())[indices]
  unigrams = [v for v in reversed(feature_names) if len(v.split(' ')) == 1][:N]
  bigrams = [v for v in reversed(feature_names) if len(v.split(' ')) == 2][:N]
  print("# '{}':".format(Product))
  print("  . Top unigrams:\n       . {}".format('\n       . '.join(unigrams)))
  print("  . Top bigrams:\n       . {}".format('\n       . '.join(bigrams)))

from sklearn import metrics
print(metrics.classification_report(y_test, y_pred, target_names=df['AggregatedDesc'].unique()))

Я не уверен, как передать данные таблицы в SO, но Вот ссылка на необработанные данные в Центре открытых данных округа Аламеда: https://data.acgov.org/datasets/76da968f7ef049a086c020191b58a83b_0/data

Может кто-нибудь сказать мне, если есть какой-то более простой метод ML, который я могу использовать, который просто прочитает мой CSV подать и назначить группы в зависимости от количества желаемых классификаций? Может быть, я смогу покончить с тренировкой в ​​столбце «Сводное описание»?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...