Skip to content

Проект хакатона Прожектор 2021, посвящённый определению доли женщин, погибших от домашнего насилия

License

LanaLob/algorithm_sveta

Repository files navigation

Алгоритм Света

Алгоритм Света - это набор программ, позволяющих по тексту судебного приговора, связанного с убийством женщины, определить, погибла ли она от рук партнера или родственника, и если да, то кто именно был убийцей. Проект стал победителем хакатона Прожектор 2021, после чего был доработан совместно с Консорциумом женских неправительственных объединений и волонтерами при поддержке Теплицы социальных технологий.

Прочитать о проекте подробнее можно здесь:

Алгоритм включает в себя:

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

Описание файлов (не все из них помещаются на гит, поэтому для некоторых даны ссылки на облако):

  • Parsers_Pravosudie_Links.ipynb - парсер ГАС Правосудие, собирающий ссылки на дела по заданным статье и году и выделяющий идентификатор дела
  • Parsers_Pravosudie_Texts.ipynb - парсер ГАС Правосудие, собирающий тексты приговоров по идентификаторам дел
  • Parsers_Mosgorsud.ipynb - парсер Мосгорсуда, собирающий тексты приговоров по заданным статье и году
  • cvect.pkl - векторизатор, позволяющий из предобработанных текстов получить матрицу документы-токены в том виде, в котором она использовалась в исследовании
  • gbc_dv.pkl - итоговая модель бинарной классификации, предсказывающая, была ли женщина в целом убита партнером или родственником
  • gbc_ipv.pkl - итоговая модель бинарной классификации, предсказывающая, была ли женщина убита именно партнером, а не родственником
  • preprocessed_data_2018.xlsx - база размеченных и предобработанных текстов для обучения моделей
  • Analysis_Models.ipynb - скрипт с процессом обучения итоговых моделей

Содержание

1. Парсеры
2. Регулярные выражения
3. Предобработка текстов
4. Обучение модели
5. Применение модели
6. Примечания

Тексты приговоров для нашего проекта собирались с двух ресурсов: сайта Мосгорсуда и ГАС Правосудие. На первом публикуют приговоры, вынесенные в судах Москвы, на втором - приговоры всех остальных судов страны, кроме московских. Технически принципы сбора данных из этих двух источников сильно различаются.

Парсер ГАС Правосудие состоит из двух частей: вначале посредством Selenium WebDriver собираются ссылки на запрашиваемые дела, из ссылок извлекаются заключенные в них идентификаторы дел, затем по идентификаторам собираются тексты с помощью пакета requests. Этот парсер работает на любых операционных системах. См. подробнее в файлах: Parsers_Pravosudie_Links.ipynb и Parsers_Pravosudie_Texts.ipynb.

Парсер Мосгорсуда также работает в несколько этапов: вначале пакетом requests собирается общая информация о делах и ссылки на их отдельные страницы, затем по этим адресам находятся ссылки на файлы с текстами приговоров, они скачиваются и прочитываются. К сожалению, этот парсер работает только на Windows, т.к. на последнем этапе тексты приговоров извлекаются из файлов Word с помощью пакета win32com. Предложения по универсализации этого этапа сильно приветствуются :) См. подробнее в файле: Parsers_Mosgorsud.ipynb

Мы собирали тексты приговоров по статьям 105, 107, 111 ч.4 УК РФ. Теоретически опубликованные парсеры адаптированы к сбору текстов любых статей при соблюдении формата запросов.

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

import re
import pandas as pd

patterns = [
    r'скончалась',
    r'погибш[аеу][йяю]',
    r'смерт[иь]ю? потерпевшей',
    r'смерт[иь]ю? последней',
    r'мертва',
    r'е[её] труп',
    r'труп женщины'
]

def check_patterns(text):
    global patterns
    
    for pattern in patterns:
        if re.search(pattern, text):
            return True
    return False

data = pd.read_csv('Ваш_файл_с_собранными_приговорами.csv')
data = data[(data['ID'].notna())&(data['text'].notna())].set_index('ID')
women_cases = data[data['text'].apply(check_patterns)]
women_cases.to_csv('Ваш_файл_с_женскими_делами.csv')

В датафрейме women_cases будут находиться отобранные "женские" дела.

Предобработка текстов для обучения, тестирования и применения моделей включает в себя три этапа: токенизацию (разбиение исходных текстов на отдельные единицы анализа), лемматизацию (приведение слов к начальной форме) и удаление стоп-слов, т.е. слов, не несущих смысловой нагрузки, но при этом часто встречающихся. При использовании кода ниже имейте в виду, что пакет pymystem3 отлично работает на Mac OS, но крайне долго - на Windows. Для Windows я рекомендую лемматизировать слова с помощью пакета pymorphy2. Процедура будет слегка отличаться, но код для нее реально найти в интернете (либо можно обратиться ко мне).

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

import re
import pymystem3
import stop_words
import pandas as pd 

mstem = pymystem3.Mystem()

def keep_only_rus(text):    
    new_text = ''
    for symbol in text:
        if re.match(r'[А-я]', symbol) or symbol == ' ':
            new_text += symbol
        else:
            new_text += ' '
    return new_text

def del_double_spaces(text_with_double_spaces):
    while '  ' in text_with_double_spaces:
        text_with_double_spaces = text_with_double_spaces.replace('  ',' ')
    return text_with_double_spaces

def lemmatize(raw_text):
    return ''.join(mstem.lemmatize(raw_text)).strip()

stopwords = stop_words.get_stop_words('russian')
stopwords.extend(stop_words.get_stop_words('english'))
stopwords = list(set(stopwords))
stopwords += [
    'фио', 'гггг', 'подсудимый', 'суд',
    'изымать', 'согласно', 'наказание',
    'потерпевший', 'показание', 'судебный',
    'преступление', 'адрес', 'свидетель',
    'свой', 'находиться', 'час', 'ход'
             ]

def del_stopwords(text):
    global stopwords
    new_text = []
    for word in text.split():
        if word not in stopwords and len(word) > 2:
            new_text.append(word)
    return ' '.join(new_text)
    
data = pd.read_csv('Ваш_файл_с_женскими_делами.csv', index_col=0) # в индексах желательно держать ID дел
data['text_prep'] = data['text'].str.lower()
data['text_prep'] = data['text_prep'].apply(keep_only_rus)
data['text_prep'] = data['text_prep'].apply(del_double_spaces)
data['text_prep'] = data['text_prep'].apply(lemmatize)
data['text_prep'] = data['text_prep'].apply(del_stopwords)
data['text_prep'] = data['text_prep'].apply(del_double_spaces)
data = data[data['text_prep'].notna()]
data.to_csv('Ваш_файл_с_женскими_делами_после_предобработки.csv')

В датафрейме data будут находиться отобранные "женские" дела после предобработки.

Обе модели, полученные по результатам работы команды, основаны на традиционном методе машинного обучения - градиентном бустинге, показавшем наивысшее качество прогноза. Целевой метрикой, которую мы максимизировали в ходе отбора моделей и на которую мы ориентировались, была precision для категории 1. Для первой модели это доля дел, помеченных алгоритмом как связанные с домашним насилием, которые действительно таковыми являются (согласно ручной разметке). Итоговый показатель этой метрики для первой модели составил 0.86. Для второй модели это доля дел, помеченных алгоритмом как дела с убийцей-партнером, которые действительно таковыми являются (согласно ручной разметке). Итоговый показатель этой метрики для первой модели составил 0.94.

Воспроизвести обучение моделей можно с помощью кода из файла Analysis_Models.ipynb и базы размеченных данных preprocessed_data_2018.xlsx. Представлены только итоговые версии используемых моделей. Попытки повысить качество моделей также приветствуются.

Применить разработанные модели можно напрямую, не обучая их. Для этого нужен лишь датафрейм с предобработанными согласно п. 3 текстами приговоров и опубликованные бинарные файлы: cvect.pkl (векторизатор), gbc_dv.pkl (модель, предсказывающая, была ли женщина в целом убита партнером или родственником), gbc_ipv.pkl (модель, предсказывающая, была ли женщина убита именно партнером, а не родственником).

import pickle
import pandas as pd

with open("cvect.pkl", 'rb') as file:
    cvect = pickle.load(file)
    
with open("gbc_dv.pkl", 'rb') as file:
    dv = pickle.load(file)
    
with open("gbc_ipv.pkl", 'rb') as file:
    ipv = pickle.load(file)
    
data = pd.read_csv('Ваш_файл_с_женскими_делами_после_предобработки.csv', index_col=0) # в индексах желательно держать ID дел
matrix = cvect.transform(data['text_prep'])
td_matrix = pd.DataFrame(matrix.toarray(), index=data.index, columns=cvect.get_feature_names())
td_matrix['DV'] = dv.predict(td_matrix)
dv_preds = td_matrix[['DV']]
td_matrix_ipv = td_matrix[td_matrix['DV']==1].drop('DV', axis=1)
td_matrix_ipv['IPV'] = ipv.predict(td_matrix_ipv)
dv_preds['IPV'] = td_matrix_ipv['IPV']

В датафрейме dv_preds для каждого дела будет сделан прогноз: столбик DV (1 - женщина была убита партнером или родственником, 0 - иначе) и столбик IPV (1 - женщина была убита партнером, 0 - родственником, NaN - иначе).

⚠ ВНИМАНИЕ!
Алгоритм Света предназначен только для анализа дел, в которых речь идет о погибших женщинах. Модели не будут давать корректных прогнозов для дел с жертвами-мужчинами, т.к. такие дела не были включены в обучающую выборку.

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

Среди файлов также отсутствует скрипт с незначительной предобработкой дел с Мосгорсуда, которая позволяет объединить базы из двух источников.

About

Проект хакатона Прожектор 2021, посвящённый определению доли женщин, погибших от домашнего насилия

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published