Введение
Классификация задач Redmine возможна при наличии доступа к данные по задачам, которые могут быть использованы для обучения модели. Redmine служит в качестве Service Desk для приёма заявок от клиентов и отслеживания статуса задач на проектах. В этой статье мы рассмотрим практический пример создания модели, которая сможет классифицировать задачи на основе предоставленных данных, с описанием каждого этапа и комментариями.
Предварительная обработка данных
Данные, полученные от Redmine, будут предварительно обработаны, включая очистку текста, преобразование категориальных данных и удаление персональных данных. Это необходимо для подготовки данных к обучению модели.
Архитектура и параметры модели
Для создания эффективной и точной модели её архитектура, библиотеки и другие параметры определены на основании опыта Best Practice на момент написания статьи (07.2023).
Модуль 1: Сбор данных с помощью Redmine
Redmine REST API и ‘python-redmine’
Python-Redmine предоставляет простой и удобный способ взаимодействия с Redmine через его REST API. Ниже приведены примеры подключения к системе, получения объектов задач, пользователей и проектов из системы с помощью данной библиотеки.
Подключение к Redmine
Для подключения нам потребуется URL сервера Redmine, а также ключ API пользователя, имеющего доступ к данным. Эти данные будут использоваться для создания экземпляра класса Redmine
, который будет использоваться для взаимодействия с системой.
from redminelib import Redmine
redmine = Redmine('https://exception.expert', username='unhex', password='passw0rd')
Code language: Python (python)
В этом примере мы подключаемся к серверу Redmine по адресу ‘https://exception.expert‘ с использованием имени пользователя ‘unhex
‘ и пароля ‘passw0rd
‘.
Получение задач по фильтру
issues = redmine.issue.filter(status_id='open')
Code language: Python (python)
В этом примере мы получаем все открытые задачи.
Получение всех задач
issues = redmine.issue.all()
Code language: Python (python)
В этом примере мы получаем все задачи.
Получение всех пользователей
users = redmine.user.all()
Code language: Python (python)
В этом примере мы получаем всех пользователей.
Получение проекта по ID
project = redmine.project.get('test_project')
Code language: Python (python)
Библиотека ‘pandas’ и работа с данными
После сбора мы сохраняем данные в формате CSV для их дальнейшего использования. Работа с данными и экспорт реализован с помощью библиотеки pandas
.
Pandas
— это библиотека Python, предоставляющая высокопроизводительные, простые в использовании структуры данных и инструменты анализа данных. Одной из основных структур данных в Pandas
является DataFrame
, который можно представить как таблицу с именованными столбцами и маркированными строками.
DataFrame
DataFrame — это двумерная структура данных, состоящая из столбцов различных типов (целые числа, строки, числа с плавающей точкой, Python-объекты и т.д.). DataFrame подобен таблице в базе данных SQL или таблице Excel.
Пример создания DataFrame
import pandas as pd
data = {
'Name': ['John', 'Anna', 'Peter'],
'Age': [28, 24, 33],
'City': ['New York', 'Paris', 'Berlin']
}
df = pd.DataFrame(data)
print(df)
Code language: Python (python)
Экспорт DataFrame в CSV
Вы можете экспортировать DataFrame в файл CSV с помощью метода to_csv()
:
df.to_csv('output.csv', index=False)
Code language: Python (python)
В этом примере DataFrame df
экспортируется в файл output.csv
. Параметр index=False
указывает, что индексы не должны сохраняться в файле.
Чтение данных из CSV
Вы также можете прочитать данные из файла CSV в DataFrame с помощью функции read_csv()
:
df = pd.read_csv('output.csv')
Code language: Python (python)
Практический пример реализации сбора данных из Redmine
# Импорт необходимых библиотек
from redminelib import Redmine
import pandas as pd
# Подключение к Redmine
redmine = Redmine('REDMINE_SERVER_URL', key='API_KEY')
# Сбор данных
issues = redmine.issue.filter(status_id='open')
# Создание DataFrame для сохранения данных
data = pd.DataFrame()
# Заполнение DataFrame данными
for issue in issues:
data = data.append({'id': issue.id, 'project': issue.project.name, 'tracker': issue.tracker.name, 'status': issue.status.name, 'priority': issue.priority.name, 'author': issue.author.name, 'subject': issue.subject, 'description': issue.description, 'start_date': issue.start_date, 'due_date': issue.due_date, 'done_ratio': issue.done_ratio, 'created_on': issue.created_on, 'updated_on': issue.updated_on}, ignore_index=True)
# Сохранение данных в CSV
data.to_csv('redmine_data.csv', index=False)
Code language: Python (python)
Модуль 2: Предварительная обработка данных
После сбора данных мы должны провести их предварительную обработку перед обучением модели. Это включает в себя очистку текста, преобразование категориальных данных и удаление персональных данных.
Очистка текста
Текстовые данные, такие как описание задачи, могут содержать много нерелевантной информации: знаки препинания, числа и стоп-слова. Для очистки текста используется библиотеку nltk
.
NLTK (Natural Language Toolkit) — это ведущая платформа для работы с человеческим языком с помощью Python. NLTK предоставляет простые в использовании интерфейсы для более 50 корпусов и лексических ресурсов, таких как WordNet. Кроме того, NLTK включает в себя библиотеки классификации текста, токенизации, стемминга, тегирования, парсинга и семантического рассуждения. Ниже мы рассмотрим несколько примеров использования данной библиотеки.
Токенизация текста
from nltk.tokenize import word_tokenize
text = "Это пример текста на русском языке."
tokens = word_tokenize(text)
print(tokens)
Code language: Python (python)
Стемминг (приведение слов к их основе)
from nltk.stem import SnowballStemmer
stemmer = SnowballStemmer("russian")
stemmed_word = stemmer.stem("бегущий")
print(stemmed_word)
Code language: Python (python)
Тегирование частей речи
from nltk import pos_tag
text = word_tokenize("Это пример текста на русском языке.")
tagged_text = pos_tag(text)
print(tagged_text)
Code language: Python (python)
Обратите внимание, что NLTK может не всегда корректно работать с русским языком, и для некоторых задач могут потребоваться специализированные инструменты, такие как pymorphy2
для морфологического анализа.
Использование WordNet для семантического анализа
WordNet — это семантическая сеть, которая может использоваться для анализа смысла слов. NLTK предоставляет интерфейс для работы с WordNet.
from nltk.corpus import wordnet as wn
dog = wn.synset('dog.n.01')
hyper = lambda s: s.hypernyms()
list(dog.closure(hyper))
Code language: JavaScript (javascript)
В этом примере мы ищем гиперонимы (более общие понятия) для слова «dog».
Для более подробной информации и примеров использования NLTK обратитесь к официальной документации NLTK, ссылки приведены в конце статьи.
Преобразование категориальных данных
Категориальные данные, такие как тип задачи и приоритет, должны быть преобразованы в числовые значения, чтобы их можно было использовать для обучения модели. Для преобразования категориальных данных в числовые мы будем использовать метод get_dummies
из библиотеки pandas
. Данный метод преобразует категориальную переменную в несколько столбцов в DataFrame, каждый из которых соответствует одной из категорий в исходной переменной. Эти новые столбцы содержат значения 0 или 1, в зависимости от того, соответствует ли данная строка данной категории.
Пример использования get_dummies
:
import pandas as pd
# Создаем DataFrame
df = pd.DataFrame({
'A': ['a', 'b', 'a'],
'B': ['b', 'a', 'c']
})
print("Original DataFrame:")
print(df)
# Применяем get_dummies
df_dummies = pd.get_dummies(df, prefix=['col_A', 'col_B'])
print("\nDataFrame after get_dummies:")
print(df_dummies)
Code language: Python (python)
В этом примере у нас есть DataFrame с двумя категориальными столбцами ‘A’ и ‘B’. Мы применяем get_dummies к этому DataFrame, что приводит к созданию нового DataFrame, где каждая уникальная категория в столбцах ‘A’ и ‘B’ становится своим собственным столбцом.
Результат выполнения этого кода:
Original DataFrame:
A B
0 a b
1 b a
2 a c
DataFrame after get_dummies:
col_A_a col_A_b col_B_a col_B_b col_B_c
0 1 0 0 1 0
1 0 1 1 0 0
2 1 0 0 0 1
Code language: Python profile (profile)
Как видно из результата, каждая уникальная категория в столбцах ‘A’ и ‘B’ стала своим собственным столбцом в новом DataFrame, и значения в этих столбцах соответствуют тому, была ли данная категория присутствует в исходной строке.
Практический пример реализации удаления персональных данных
Персональные данные, такие как имя автора, должны быть удалены из данных в соответствии с политикой конфиденциальности. Для удаления этих данных мы будем использовать метод drop
из библиотеки pandas
.
# Импорт необходимых библиотек
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
# Загрузка данных
data = pd.read_csv('redmine_data.csv')
# Очистка текста
stop_words = set(stopwords.words('english'))
data['description'] = data['description'].str.lower().apply(word_tokenize).apply(lambda x: [item for item in x if item not in stop_words])
# Преобразование категориальных данных
data = pd.get_dummies(data, columns=['tracker', 'status', 'priority'])
# Удаление персональных данных
data = data.drop(columns=['author'])
# Вывод обработанных данных
print(data.head())
Code language: Python (python)
Модуль 3: Определение архитектуры и параметров модели
После предварительной обработки данных мы можем перейти к определению архитектуры и параметров модели. Для создания модели будем использовать библиотеку keras
.
Keras — это мощная и простая в использовании бесплатная открытая библиотека Python для разработки и оценки моделей глубокого обучения. Является высоко-уровневым API TensorFlow и служит доступным и чрезвычайно продуктивным решением, предлагающим высокопроизводительный интерфейс для решения задач машинного обучения (ML), с акцентом на современное глубокое обучение.
Возможные области применения Keras:
- Распознавание изображений и обработка видео. Широко используется для создания моделей, способных классифицировать изображения или распознавать объекты на видео.
- Обработка естественного языка. Может быть использован для анализа текста, перевода языка, а также для создания чат-ботов и систем автоматического ответа на вопросы.
- Прогнозирование временных рядов. Может быть использован для анализа временных рядов и прогнозирования будущих значений на основе исторических данных.
- Рекомендательные системы. Может быть использован для создания систем, которые рекомендуют продукты или услуги пользователям на основе их предыдущего поведения.
Архитектура модели
Архитектуру модели определили на основании опыта Best Practice. Для создания модели будем использовать слои Embedding
, LSTM
и Dense
. Данные слои используются вместе для создания моделей глубокого обучения, которые могут обрабатывать различные типы входных данных и решать различные задачи.
Embedding
Этот слой используется для преобразования входных данных, которые обычно представлены в виде целочисленных кодов (например, слова в тексте), в векторы фиксированной длины. Это делается для того, чтобы модель могла обрабатывать входные данные как непрерывные, а не категориальные значения. Векторы, созданные с помощью слоя Embedding, обычно содержат много информации о входных данных, такой как семантические и синтаксические отношения между словами в тексте.
LSTM (Long Short-Term Memory)
LSTM — это тип рекуррентной нейронной сети (RNN), который способен обучаться и запоминать информацию в течение длительных периодов времени. Это делает LSTM идеально подходящим для обработки последовательностей и временных рядов, таких как тексты или временные ряды. LSTM слои обычно используются в моделях глубокого обучения для обработки входных данных, которые имеют временную структуру.
Dense
Dense слой, также известный как полносвязный слой, это базовый слой в нейронных сетях, где каждый входной нейрон связан со всеми выходными нейронами. Dense слои обычно используются в конце модели после других слоев, таких как LSTM или Convolutional, для генерации окончательного вывода модели. В Dense слое каждый входной элемент связан с каждым выходом, и каждое соединение имеет свой вес. Эти веса обновляются в процессе обучения модели.
Параметры модели
Параметры модели, такие как количество эпох, размер партии и скорость обучения, так же выбраны нами после исследования опыта коллег (на основании Best Practice). Далее рассмотрим основные параметры и то как мы определяем параметры с помощью метода compile
в Keras.
Количество эпох (epochs)
Эпоха — это один полный проход по всему набору обучающих данных. Количество эпох определяет, сколько раз алгоритм обучения будет работать по всему обучающему набору данных. Например, если у вас есть 1000 обучающих примеров, и вы установили количество эпох равным 10, то алгоритм обучения будет работать по всему набору данных 10 раз.
Размер партии (batch size)
Размер партии определяет количество обучающих примеров, обрабатываемых одновременно перед обновлением параметров модели. Например, если размер партии равен 100, то каждый раз, когда параметры модели обновляются, используется 100 обучающих примеров.
Скорость обучения (learning rate)
Скорость обучения — это параметр, который определяет, насколько быстро или медленно обновляются параметры модели. Если скорость обучения слишком высока, модель может пропустить оптимальное решение. Если скорость обучения слишком низкая, обучение может занять слишком много времени.
Определение параметров. Метод ‘compile’
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import SGD
# создание модели
model = Sequential()
model.add(Dense(10, input_dim=8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# определение параметров обучения
optimizer = SGD(lr=0.01) # скорость обучения равна 0.01
model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy'])
# обучение модели
model.fit(X, y, epochs=10, batch_size=32) # 10 эпох, размер партии 32
Code language: Python (python)
В этом примере мы используем стохастический градиентный спуск (SGD) в качестве оптимизатора с скоростью обучения 0.01
. Мы обучаем модель в течение 10
эпох с размером партии 32
. Функция потерь ‘binary_crossentropy
‘ используется для бинарной классификации, и мы отслеживаем точность в качестве метрики.
Обучение модели
После определения архитектуры и параметров, для обучения модели на обработанных данных, используется метод fit
. Данный метод используется для обучения модели на определенное количество эпох (итераций по набору данных).
Метод fit
Базовый пример использования:
history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_val, y_val))
Code language: Python (python)
В этом примере X_train
и y_train
— это обучающие данные и соответствующие им метки. Параметр epochs
определяет, сколько раз модель будет обучаться на всем наборе данных, а batch_size
определяет количество обучающих примеров, которые модель видит перед обновлением своих весов.
validation_data
— это данные, на которых модель проверяется после каждой эпохи. Это позволяет наблюдать за производительностью модели на данных, которые она не видела во время обучения, что может помочь обнаружить переобучение.
Объект history
Метод fit
возвращает объект History
, который содержит записи значений функции потерь и метрик модели на каждой эпохе. Это может быть полезно для визуализации процесса обучения. Например, вы можете построить график потерь на обучающих и валидационных данных во время обучения следующим образом:
import matplotlib.pyplot as plt
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Val'], loc='upper right')
plt.show()
Code language: Python (python)
Этот график покажет, как функция потерь модели меняется во время обучения, и может помочь вам определить, когда модель начинает переобучаться.
Практический пример архитектуры, параметров и обучения модели
# Импорт необходимых библиотек
from keras.models import Sequential
from keras.layers import Embedding, LSTM, Dense
# Определение архитектуры модели
model = Sequential()
model.add(Embedding(input_dim=10000, output_dim=32))
model.add(LSTM(32))
model.add(Dense(1, activation='sigmoid'))
# Определение параметров модели
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
# Обучение модели
history = model.fit(data, labels, epochs=10, batch_size=128, validation_split=0.2)
Code language: Python (python)
Модуль 4: Оценка и тестирование модели
После обучения модели мы должны оценить ее производительность и протестировать ее на новых данных.
Оценка модели
Для оценки производительности модели на тестовых данных используется метод evaluate
.
Метод evaluate
в Keras используется для оценки производительности обученной модели на тестовых данных. Он возвращает значение функции потерь и метрик, которые были определены при компиляции модели.
Вот пример использования метода evaluate
:
loss, accuracy = model.evaluate(X_test, y_test, verbose=0)
print('Test loss:', loss)
print('Test accuracy:', accuracy)
Code language: Python (python)
В этом примере X_test
и y_test
— это тестовые данные и соответствующие им метки. Метод evaluate
возвращает значение функции потерь и метрик на тестовых данных. В этом случае мы получаем потери и точность модели на тестовых данных.
Параметр verbose
контролирует, сколько информации выводится в процессе оценки. Если verbose=0
, информация не выводится, если verbose=1
, выводится прогресс-бар, а если verbose=2
, для каждой эпохи выводится одна строка лога.
Полученные значения потерь и точности можно использовать для сравнения производительности различных моделей или конфигураций модели.
Тестирование модели
Метод predict
используется для тестирования модели на новых данных. Этот метод возвращает предсказанные метки для входных данных.
Вот пример использования метода predict
:
new_data = np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]])
predictions = model.predict(new_data)
print('Predictions:', predictions)
Code language: Python (python)
В этом примере new_data
— это новые данные, для которых мы хотим получить предсказания. Мы передаем эти данные в метод predict
, и он возвращает предсказанные метки.
Обратите внимание, что входные данные должны иметь ту же форму, что и обучающие данные. В этом примере мы предполагаем, что модель была обучена на данных с восемью признаками, поэтому мы передаем один пример с восемью признаками.
Полученные предсказания могут быть использованы для дальнейшего анализа или для создания отчетов о производительности модели.
Визуализация результатов
Библиотеку matplotlib
используем для визуализации результатов обучения и тестирования модели. С помощью неё мы будем визуализировать потери и точность модели на каждой эпохе обучения.
Визуализация истории обучения
После обучения модели с помощью метода fit
, вы можете визуализировать изменение потерь и метрик во время обучения. Вот пример:
history = model.fit(X_train, y_train, epochs=10, validation_data=(X_val, y_val))
# Визуализация истории обучения
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Losses')
plt.xlabel('Epoch')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='Train Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Accuracies')
plt.xlabel('Epoch')
plt.legend()
plt.tight_layout()
plt.show()
Code language: Python (python)
Визуализация результатов предсказаний
Вы также можете визуализировать результаты предсказаний модели. Вот пример для задачи регрессии:
# Предсказания модели
predictions = model.predict(X_test)
# Визуализация предсказаний
plt.figure(figsize=(8, 8))
plt.scatter(y_test, predictions)
plt.xlabel('True Values')
plt.ylabel('Predictions')
plt.axis('equal')
plt.axis('square')
plt.xlim([0,plt.xlim()[1]])
plt.ylim([0,plt.ylim()[1]])
_ = plt.plot([-100, 100], [-100, 100])
plt.show()
Code language: Python (python)
В этом примере мы предсказываем значения y_test
на основе X_test
и затем визуализируем истинные значения по сравнению с предсказаниями. Если модель идеальна, точки должны лежать вдоль диагонали.
Практический пример визуализации потерь и точности эпохи
# Импорт необходимых библиотек
import matplotlib.pyplot as plt
# Оценка модели
loss, acc = model.evaluate(test_data, test_labels)
print(f'Loss: {loss}, Accuracy: {acc}')
# Тестирование модели
predictions = model.predict(new_data)
# Визуализация результатов
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.legend()
plt.title('Loss')
plt.subplot(1, 2, 2)
plt.plot(history.history['acc'], label='Training Accuracy')
plt.plot(history.history['val_acc'], label='Validation Accuracy')
plt.legend()
plt.title('Accuracy')
plt.tight_layout()
plt.show()
Code language: Python (python)