{"id":330626,"date":"2022-03-14T15:00:35","date_gmt":"2022-03-14T15:00:35","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=330626"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=330626","title":{"rendered":"<span>\u041a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u0432<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u043e\u0434\u0435\u043b\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u0432 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f state-of-the-art \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 \u043c\u0438\u0440\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430. \u041d\u043e\u0432\u044b\u0435, \u0431\u043e\u043b\u0435\u0435 \u043a\u0440\u0443\u043f\u043d\u044b\u0435 \u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0441\u044f\u0446, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044f \u043d\u043e\u0432\u044b\u0435 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u043c\u0443 \u043a\u0440\u0443\u0433\u0443 \u0437\u0430\u0434\u0430\u0447. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 \u0434\u043b\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d81\/1ff\/8b9\/d811ff8b9dd983ec4511adec51487837.png\" width=\"623\" height=\"348\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d81\/1ff\/8b9\/d811ff8b9dd983ec4511adec51487837.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439. \u0421\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u043a\u0430 \u2013 TF-IDF + \u043b\u0438\u043d\u0435\u0439\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0440\u0435\u0448\u0430\u0442\u044c \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u044b\u0445 \u0437\u0430\u0442\u0440\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u0439 \u0441\u0432\u044f\u0437\u043a\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439: \u0447\u0438\u0441\u0442\u043a\u0430, \u043b\u0435\u043c\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 BERT \u043c\u043e\u0436\u043d\u043e (\u0434\u0430\u0436\u0435 \u043d\u0443\u0436\u043d\u043e) \u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044e. \u041f\u043e\u043c\u0438\u043c\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432, \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0447\u0430\u0441\u0442\u043e \u0432\u044b\u0434\u0430\u044e\u0442 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u043b\u043e\u0432. \u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u0432.<\/p>\n<p>\u041d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0442\u0435\u043c\u044b. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0443\u0447\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0441 \u0436\u0430\u043b\u043e\u0431\u043e\u0439 \u043d\u0430 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u2013 \u0431\u0438\u043d\u0430\u0440\u043d\u0430\u044f \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d77\/7c7\/8d5\/d777c78d5735020822355232374c891a.png\" width=\"1312\" height=\"455\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d77\/7c7\/8d5\/d777c78d5735020822355232374c891a.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0442 DeepPavlov rubert-base-cased-sentence. \u042d\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0431\u0443\u0447\u0430\u043b\u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code>import re import numpy as np import pandas as pd from tqdm import tqdm from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report, f1_score  import torch import transformers import torch.nn as nn from transformers import AutoModel, BertTokenizer, BertForSequenceClassification from torch.utils.data import TensorDataset, DataLoader, RandomSampler, SequentialSampler  tqdm.pandas()  device = torch.device('cuda') <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u0435\u0434\u043e\u0431\u0443\u0447\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c. <\/p>\n<pre><code>bert = AutoModel.from_pretrained('rubert_base_cased_sentence\/')  tokenizer = BertTokenizer.from_pretrained('rubert_base_cased_sentence\/') <\/code><\/pre>\n<p>\u0414\u043b\u044f Bert \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u043e\u0431\u0443\u0447\u0430\u043b\u0441\u044f \u043d\u0430 \u0442\u0430\u043a\u0438\u0445 \u0436\u0435 \u0433\u0440\u044f\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041c\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0440\u0430\u0437\u0431\u0438\u043b \u043d\u0430 train \/ val \/ test \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u0432 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u044f\u0445 60\/20\/20. \u0420\u0430\u0437\u043e\u0431\u044c\u0435\u043c \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 \u0438 \u0442\u0430\u0440\u0433\u0435\u0442:<\/p>\n<pre><code>train_text = train_df['text'].astype('str') train_labels = train_df['target'] val_text = val_df['text'].astype('str') val_labels = val_df['target'] test_text = test_df['text'].astype('str') test_labels = test_df['target'] <\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0432\u044b\u0432\u0435\u0434\u0435\u0442 \u0433\u0440\u0430\u0444\u0438\u043a \u0434\u043b\u0438\u043d \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041e\u043d \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043b\u0438\u043d\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432.<\/p>\n<pre><code>seq_len = [len(str(i).split()) for i in train_text] pd.Series(seq_len).hist(bins = 50)<\/code><\/pre>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/40f\/d40\/e99\/40fd40e992a8aef6e71cf18606b69420.png\" width=\"335\" height=\"217\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/40f\/d40\/e99\/40fd40e992a8aef6e71cf18606b69420.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u00ab\u041d\u0430 \u0433\u043b\u0430\u0437\u043e\u043a\u00bb 50 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0445\u0432\u0430\u0442\u0438\u0442. \u0422\u043e\u043a\u0435\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u0442\u0435\u043d\u0437\u043e\u0440\u044b \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e DataLoader, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0432 \u043c\u043e\u0434\u0435\u043b\u044c:<\/p>\n<pre><code>tokens_train = tokenizer.batch_encode_plus(     train_text.values,     max_length = 50,     padding = 'max_length',     truncation = True ) tokens_val = tokenizer.batch_encode_plus(     val_text.values,     max_length = 50,     padding = 'max_length',     truncation = True ) tokens_test = tokenizer.batch_encode_plus(     test_text.values,     max_length = 50,     padding = 'max_length',     truncation = True )  train_seq = torch.tensor(tokens_train['input_ids']) train_mask = torch.tensor(tokens_train['attention_mask']) train_y = torch.tensor(train_labels.values)  val_seq = torch.tensor(tokens_val['input_ids']) val_mask = torch.tensor(tokens_val['attention_mask']) val_y = torch.tensor(val_labels.values)  test_seq = torch.tensor(tokens_test['input_ids']) test_mask = torch.tensor(tokens_test['attention_mask']) test_y = torch.tensor(test_labels.values) batch_size = 8   train_data = TensorDataset(train_seq, train_mask, train_y) train_sampler = RandomSampler(train_data) train_dataloader = DataLoader(train_data, sampler = train_sampler, batch_size = batch_size)  val_data =  TensorDataset(val_seq, val_mask, val_y) val_sampler = SequentialSampler(val_data) val_dataloader = DataLoader(val_data, sampler = val_sampler, batch_size = batch_size)<\/code><\/pre>\n<p>\u0421\u0430\u043c BERT \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. \u0414\u043e\u043f\u0438\u0448\u0435\u043c \u043a \u0435\u0433\u043e \u0432\u044b\u0445\u043e\u0434\u0443 \u0441\u0432\u043e\u0438 \u0441\u043b\u043e\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e. <\/p>\n<pre><code>for param in bert.parameters():     param.requires_grad = False  class BERT_Arch(nn.Module):          def __init__(self, bert):         super(BERT_Arch, self).__init__()         self.bert = bert         self.dropout = nn.Dropout(0.1)         self.relu = nn.ReLU()         self.fc1 = nn.Linear(768,512)         self.fc2 = nn.Linear(512,2)         self.softmax = nn.LogSoftmax(dim = 1)          def forward(self, sent_id, mask):         _, cls_hs = self.bert(sent_id, attention_mask = mask, return_dict = False)         x = self.fc1(cls_hs)         x = self.relu(x)         x = self.dropout(x)         x = self.fc2(x)         x = self.softmax(x)         return x<\/code><\/pre>\n<p>\u00a0\u041e\u0431\u044a\u044f\u0432\u0438\u043c \u043c\u043e\u0434\u0435\u043b\u044c, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0435\u0435 \u0432 GPU. \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440.<\/p>\n<pre><code>model = BERT_Arch(bert)  model = model.to(device) from transformers import AdamW  optimizer = AdamW(model.parameters(),<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0431\u043e\u0440\u044c\u0431\u044b \u0441 \u0434\u0438\u0441\u0431\u0430\u043b\u0430\u043d\u0441\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434:<\/p>\n<pre><code>from sklearn.utils.class_weight import compute_class_weight  class_weights = compute_class_weight('balanced', np.unique(train_labels), train_labels)  print(class_weights) [0.8086199  1.31005794]  weights = torch.tensor(class_weights, dtype = torch.float) weights = weights.to(device) cross_entropy = nn.CrossEntropyLoss() epochs = 20 <\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code>def train():     model.train()     total_loss, total_accuracy = 0, 0     total_preds = []          for step, batch in tqdm(enumerate(train_dataloader), total = len(train_dataloader)):         batch = [r.to(device) for r in batch]         sent_id,mask,labels = batch         model.zero_grad()         preds = model(sent_id, mask)         loss = cross_entropy(preds, labels)         total_loss += loss.item()         loss.backward()         torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)         optimizer.step()         preds = preds.detach().cpu().numpy()         total_preds.append(preds)              avg_loss = total_loss \/ len(train_dataloader)     total_preds = np.concatenate(total_preds, axis = 0)          return avg_loss, total_preds <\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438:<\/p>\n<pre><code>def evaluate():     model.eval()     total_loss, total_accuracy = 0,0     total_preds = []      for step, batch in tqdm(enumerate(val_dataloader), total = len(val_dataloader)):         batch = [t.to(device) for t in batch]         sent_id, mask, labels = batch                  with torch.no_grad():             preds = model(sent_id, mask)             loss = cross_entropy(preds, labels)             total_loss = total_loss + loss.item()             preds = preds.detach().cpu().numpy()             total_preds.append(preds)      avg_loss = total_loss \/ len(val_dataloader)     total_preds = np.concatenate(total_preds, axis = 0) <\/code><\/pre>\n<p>\u041e\u0431\u0443\u0447\u0430\u0435\u043c. \u0414\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0439 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432\u0435\u0441\u0430:<\/p>\n<pre><code>best_valid_loss = float('inf')  train_losses = [] valid_losses = []  for epoch in range(epochs):     print('\\n Epoch{:} \/ {:}'.format(epoch+1, epochs))          train_loss, _ = train()     valid_loss, _ = evaluate()          if valid_loss &lt; best_valid_loss:         best_valid_loss = valid_loss         torch.save(model.state_dict(), 'saved_weights.pt')          train_losses.append(train_loss)     valid_losses.append(valid_loss)     print(f'\\nTraining loss: {train_loss:.3f}')     print(f'Validation loss: {valid_loss:.3f}') <\/code><\/pre>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u043e\u0431\u0443\u0447\u0438\u043b\u0438 \u043c\u043e\u0434\u0435\u043b\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0438 \u0435\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0431\u043e\u0435\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043b\u0443\u0447\u0448\u0438\u0435 \u0432\u0435\u0441\u0430 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code>path = 'saved_weights.pt' model.load_state_dict(torch.load(path))<\/code><\/pre>\n<p>\u0412\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u043e \u0447\u0442\u043e \u0432 \u043d\u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043a\u043e\u0441\u0442\u044b\u043b\u044c. \u0420\u0430\u0437\u043e\u0431\u044c\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c<\/p>\n<pre><code>import gc gc.collect() torch.cuda.empty_cache()  list_seq = np.array_split(test_seq, 50) list_mask = np.array_split(test_mask, 50)   predictions = [] for num, elem in enumerate(list_seq):     with torch.no_grad():         preds = model(elem.to(device), list_mask[num].to(device))         predictions.append(preds.detach().cpu().numpy())<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0432 \u043e\u0434\u0438\u043d \u0441\u043f\u0438\u0441\u043e\u043a, \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0432 \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0438\u043a \u0434\u0430\u0442\u0430\u0444\u0440\u0435\u0439\u043c\u0430.<\/p>\n<pre><code>flat_preds = [item[1] for sublist in predictions for item in sublist] flat_preds = (flat_preds - min(flat_preds)) \/ (max(flat_preds) - min(flat_preds)) test_df['confidence'] = flat_preds<\/code><\/pre>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u043e\u0442 0 \u0434\u043e 1. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u0435\u043d\u044f\u044f \u043f\u043e\u0440\u043e\u0433, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code>test_df['pred'] = test_df['confidence'].apply(lambda x: 1 if x>0.92 else 0)  print(classification_report(test_df['target'], test_df['pred']))                   precision    recall  f1-score   support             0       0.91      0.91      0.91     21831            1       0.85      0.85      0.85     13460      accuracy                           0.89     35291    macro avg       0.88      0.88      0.88     35291 weighted avg       0.89      0.89      0.89     35291 <\/code><\/pre>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043c\u0435\u0442\u0440\u0438\u043a\u0443 f1 = 0.91 \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0434\u0435\u043b\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.   <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac0\/2db\/d4e\/ac02dbd4e363b11ae7c85329d90822e4.png\" width=\"1321\" height=\"534\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ac0\/2db\/d4e\/ac02dbd4e363b11ae7c85329d90822e4.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0432\u0437\u044f\u0442\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b.<\/p>\n<p>\u0412\u044b\u0432\u043e\u0434:<\/p>\n<p>\u041e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 \u0441\u0430\u0439\u0442\u0430\u0445 HuggingFace \u0438 DeepPavlov. \u0421\u0435\u0439\u0447\u0430\u0441 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u044b \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0437\u0443 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0437\u0430\u0434\u0430\u0447. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0432\u0437\u044f\u0442\u044c \u043f\u0440\u0435\u0434\u043e\u0431\u0443\u0447\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0438 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b.<\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0446\u0435\u043b\u044b\u043c\u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0435\u0435 \u0434\u043b\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041f\u043e\u043c\u0438\u043c\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0438\u0437\u043c\u0435\u043d\u0438\u0432 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0445\u043e\u0434\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u043e\u0441\u0438\u043d\u0443\u0441\u043d\u043e\u0433\u043e \u0441\u0445\u043e\u0434\u0441\u0442\u0432\u0430 \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043a\u0441\u0442\u0430\u043c\u0438. \u041e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u043c\u044b\u0441\u043b \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0430 \u0446\u0435\u043b\u044b\u0445 \u0442\u0435\u043a\u0441\u0442\u043e\u0432.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/655517\/\"> https:\/\/habr.com\/ru\/post\/655517\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u043e\u0434\u0435\u043b\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u0432 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f state-of-the-art \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 \u043c\u0438\u0440\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430. \u041d\u043e\u0432\u044b\u0435, \u0431\u043e\u043b\u0435\u0435 \u043a\u0440\u0443\u043f\u043d\u044b\u0435 \u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0441\u044f\u0446, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044f \u043d\u043e\u0432\u044b\u0435 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u043c\u0443 \u043a\u0440\u0443\u0433\u0443 \u0437\u0430\u0434\u0430\u0447. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 \u0434\u043b\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439. \u0421\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u043a\u0430 \u2013 TF-IDF + \u043b\u0438\u043d\u0435\u0439\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0440\u0435\u0448\u0430\u0442\u044c \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u044b\u0445 \u0437\u0430\u0442\u0440\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u0439 \u0441\u0432\u044f\u0437\u043a\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439: \u0447\u0438\u0441\u0442\u043a\u0430, \u043b\u0435\u043c\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 BERT \u043c\u043e\u0436\u043d\u043e (\u0434\u0430\u0436\u0435 \u043d\u0443\u0436\u043d\u043e) \u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044e. \u041f\u043e\u043c\u0438\u043c\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u043e\u0432, \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0447\u0430\u0441\u0442\u043e \u0432\u044b\u0434\u0430\u044e\u0442 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u043b\u043e\u0432. \u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u0432.<\/p>\n<p>\u041d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0442\u0435\u043c\u044b. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0443\u0447\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0441 \u0436\u0430\u043b\u043e\u0431\u043e\u0439 \u043d\u0430 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u2013 \u0431\u0438\u043d\u0430\u0440\u043d\u0430\u044f \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0442 DeepPavlov rubert-base-cased-sentence. \u042d\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0431\u0443\u0447\u0430\u043b\u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code>import re import numpy as np import pandas as pd from tqdm import tqdm from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report, f1_score  import torch import transformers import torch.nn as nn from transformers import AutoModel, BertTokenizer, BertForSequenceClassification from torch.utils.data import TensorDataset, DataLoader, RandomSampler, SequentialSampler  tqdm.pandas()  device = torch.device('cuda') <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u0435\u0434\u043e\u0431\u0443\u0447\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c. <\/p>\n<pre><code>bert = AutoModel.from_pretrained('rubert_base_cased_sentence\/')  tokenizer = BertTokenizer.from_pretrained('rubert_base_cased_sentence\/') <\/code><\/pre>\n<p>\u0414\u043b\u044f Bert \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u043e\u0431\u0443\u0447\u0430\u043b\u0441\u044f \u043d\u0430 \u0442\u0430\u043a\u0438\u0445 \u0436\u0435 \u0433\u0440\u044f\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041c\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0440\u0430\u0437\u0431\u0438\u043b \u043d\u0430 train \/ val \/ test \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u0432 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u044f\u0445 60\/20\/20. \u0420\u0430\u0437\u043e\u0431\u044c\u0435\u043c \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 \u0438 \u0442\u0430\u0440\u0433\u0435\u0442:<\/p>\n<pre><code>train_text = train_df['text'].astype('str') train_labels = train_df['target'] val_text = val_df['text'].astype('str') val_labels = val_df['target'] test_text = test_df['text'].astype('str') test_labels = test_df['target'] <\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0432\u044b\u0432\u0435\u0434\u0435\u0442 \u0433\u0440\u0430\u0444\u0438\u043a \u0434\u043b\u0438\u043d \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041e\u043d \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043b\u0438\u043d\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0436\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432.<\/p>\n<pre><code>seq_len = [len(str(i).split()) for i in train_text] pd.Series(seq_len).hist(bins = 50)<\/code><\/pre>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u00ab\u041d\u0430 \u0433\u043b\u0430\u0437\u043e\u043a\u00bb 50 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0445\u0432\u0430\u0442\u0438\u0442. \u0422\u043e\u043a\u0435\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u0442\u0435\u043d\u0437\u043e\u0440\u044b \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e DataLoader, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0432 \u043c\u043e\u0434\u0435\u043b\u044c:<\/p>\n<pre><code>tokens_train = tokenizer.batch_encode_plus(     train_text.values,     max_length = 50,     padding = 'max_length',     truncation = True ) tokens_val = tokenizer.batch_encode_plus(     val_text.values,     max_length = 50,     padding = 'max_length',     truncation = True ) tokens_test = tokenizer.batch_encode_plus(     test_text.values,     max_length = 50,     padding = 'max_length',     truncation = True )  train_seq = torch.tensor(tokens_train['input_ids']) train_mask = torch.tensor(tokens_train['attention_mask']) train_y = torch.tensor(train_labels.values)  val_seq = torch.tensor(tokens_val['input_ids']) val_mask = torch.tensor(tokens_val['attention_mask']) val_y = torch.tensor(val_labels.values)  test_seq = torch.tensor(tokens_test['input_ids']) test_mask = torch.tensor(tokens_test['attention_mask']) test_y = torch.tensor(test_labels.values) batch_size = 8   train_data = TensorDataset(train_seq, train_mask, train_y) train_sampler = RandomSampler(train_data) train_dataloader = DataLoader(train_data, sampler = train_sampler, batch_size = batch_size)  val_data =  TensorDataset(val_seq, val_mask, val_y) val_sampler = SequentialSampler(val_data) val_dataloader = DataLoader(val_data, sampler = val_sampler, batch_size = batch_size)<\/code><\/pre>\n<p>\u0421\u0430\u043c BERT \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. \u0414\u043e\u043f\u0438\u0448\u0435\u043c \u043a \u0435\u0433\u043e \u0432\u044b\u0445\u043e\u0434\u0443 \u0441\u0432\u043e\u0438 \u0441\u043b\u043e\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e. <\/p>\n<pre><code>for param in bert.parameters():     param.requires_grad = False  class BERT_Arch(nn.Module):          def __init__(self, bert):         super(BERT_Arch, self).__init__()         self.bert = bert         self.dropout = nn.Dropout(0.1)         self.relu = nn.ReLU()         self.fc1 = nn.Linear(768,512)         self.fc2 = nn.Linear(512,2)         self.softmax = nn.LogSoftmax(dim = 1)          def forward(self, sent_id, mask):         _, cls_hs = self.bert(sent_id, attention_mask = mask, return_dict = False)         x = self.fc1(cls_hs)         x = self.relu(x)         x = self.dropout(x)         x = self.fc2(x)         x = self.softmax(x)         return x<\/code><\/pre>\n<p>\u00a0\u041e\u0431\u044a\u044f\u0432\u0438\u043c \u043c\u043e\u0434\u0435\u043b\u044c, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0435\u0435 \u0432 GPU. \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440.<\/p>\n<pre><code>model = BERT_Arch(bert)  model = model.to(device) from transformers import AdamW  optimizer = AdamW(model.parameters(),<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0431\u043e\u0440\u044c\u0431\u044b \u0441 \u0434\u0438\u0441\u0431\u0430\u043b\u0430\u043d\u0441\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434:<\/p>\n<pre><code>from sklearn.utils.class_weight import compute_class_weight  class_weights = compute_class_weight('balanced', np.unique(train_labels), train_labels)  print(class_weights) [0.8086199  1.31005794]  weights = torch.tensor(class_weights, dtype = torch.float) weights = weights.to(device) cross_entropy = nn.CrossEntropyLoss() epochs = 20 <\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code>def train():     model.train()     total_loss, total_accuracy = 0, 0     total_preds = []          for step, batch in tqdm(enumerate(train_dataloader), total = len(train_dataloader)):         batch = [r.to(device) for r in batch]         sent_id,mask,labels = batch         model.zero_grad()         preds = model(sent_id, mask)         loss = cross_entropy(preds, labels)         total_loss += loss.item()         loss.backward()         torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)         optimizer.step()         preds = preds.detach().cpu().numpy()         total_preds.append(preds)              avg_loss = total_loss \/ len(train_dataloader)     total_preds = np.concatenate(total_preds, axis = 0)          return avg_loss, total_preds <\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438:<\/p>\n<pre><code>def evaluate():     model.eval()     total_loss, total_accuracy = 0,0     total_preds = []      for step, batch in tqdm(enumerate(val_dataloader), total = len(val_dataloader)):         batch = [t.to(device) for t in batch]         sent_id, mask, labels = batch                  with torch.no_grad():             preds = model(sent_id, mask)             loss = cross_entropy(preds, labels)             total_loss = total_loss + loss.item()             preds = preds.detach().cpu().numpy()             total_preds.append(preds)      avg_loss = total_loss \/ len(val_dataloader)     total_preds = np.concatenate(total_preds, axis = 0) <\/code><\/pre>\n<p>\u041e\u0431\u0443\u0447\u0430\u0435\u043c. \u0414\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0439 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432\u0435\u0441\u0430:<\/p>\n<pre><code>best_valid_loss = float('inf')  train_losses = [] valid_losses = []  for epoch in range(epochs):     print('\\n Epoch{:} \/ {:}'.format(epoch+1, epochs))          train_loss, _ = train()     valid_loss, _ = evaluate()          if valid_loss &lt; best_valid_loss:         best_valid_loss = valid_loss         torch.save(model.state_dict(), 'saved_weights.pt')          train_losses.append(train_loss)     valid_losses.append(valid_loss)     print(f'\\nTraining loss: {train_loss:.3f}')     print(f'Validation loss: {valid_loss:.3f}') <\/code><\/pre>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u043e\u0431\u0443\u0447\u0438\u043b\u0438 \u043c\u043e\u0434\u0435\u043b\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0438 \u0435\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0431\u043e\u0435\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043b\u0443\u0447\u0448\u0438\u0435 \u0432\u0435\u0441\u0430 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code>path = 'saved_weights.pt' model.load_state_dict(torch.load(path))<\/code><\/pre>\n<p>\u0412\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u043e \u0447\u0442\u043e \u0432 \u043d\u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043a\u043e\u0441\u0442\u044b\u043b\u044c. \u0420\u0430\u0437\u043e\u0431\u044c\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c<\/p>\n<pre><code>import gc gc.collect() torch.cuda.empty_cache()  list_seq = np.array_split(test_seq, 50) list_mask = np.array_split(test_mask, 50)   predictions = [] for num, elem in enumerate(list_seq):     with torch.no_grad():         preds = model(elem.to(device), list_mask[num].to(device))         predictions.append(preds.detach().cpu().numpy())<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0432 \u043e\u0434\u0438\u043d \u0441\u043f\u0438\u0441\u043e\u043a, \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0432 \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0438\u043a \u0434\u0430\u0442\u0430\u0444\u0440\u0435\u0439\u043c\u0430.<\/p>\n<pre><code>flat_preds = [item[1] for sublist in predictions for item in sublist] flat_preds = (flat_preds - min(flat_preds)) \/ (max(flat_preds) - min(flat_preds)) test_df['confidence'] = flat_preds<\/code><\/pre>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u043e\u0442 0 \u0434\u043e 1. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u0435\u043d\u044f\u044f \u043f\u043e\u0440\u043e\u0433, \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code>test_df['pred'] = test_df['confidence'].apply(lambda x: 1 if x>0.92 else 0)  print(classification_report(test_df['target'], test_df['pred']))                   precision    recall  f1-score   support             0       0.91      0.91      0.91     21831            1       0.85      0.85      0.85     13460      accuracy                           0.89     35291    macro avg       0.88      0.88      0.88     35291 weighted avg       0.89      0.89      0.89     35291 <\/code><\/pre>\n<p>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043c\u0435\u0442\u0440\u0438\u043a\u0443 f1 = 0.91 \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0434\u0435\u043b\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.   <\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0432\u0437\u044f\u0442\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b.<\/p>\n<p>\u0412\u044b\u0432\u043e\u0434:<\/p>\n<p>\u041e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 \u0441\u0430\u0439\u0442\u0430\u0445 HuggingFace \u0438 DeepPavlov. \u0421\u0435\u0439\u0447\u0430\u0441 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e \u043e\u0431\u0443\u0447\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u044b \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0437\u0443 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0441\u043f\u0435\u043a\u0442\u0440\u0430 \u0437\u0430\u0434\u0430\u0447. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0432\u0437\u044f\u0442\u044c \u043f\u0440\u0435\u0434\u043e\u0431\u0443\u0447\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0438 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b.<\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0446\u0435\u043b\u044b\u043c\u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0435\u0435 \u0434\u043b\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041f\u043e\u043c\u0438\u043c\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0438\u0437\u043c\u0435\u043d\u0438\u0432 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0445\u043e\u0434\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u043e\u0441\u0438\u043d\u0443\u0441\u043d\u043e\u0433\u043e \u0441\u0445\u043e\u0434\u0441\u0442\u0432\u0430 \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043a\u0441\u0442\u0430\u043c\u0438. \u041e\u0431\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u043c\u044b\u0441\u043b \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0430 \u0446\u0435\u043b\u044b\u0445 \u0442\u0435\u043a\u0441\u0442\u043e\u0432.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/655517\/\"> https:\/\/habr.com\/ru\/post\/655517\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-330626","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330626","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=330626"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330626\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=330626"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=330626"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=330626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}