Untitled
unknown
plain_text
2 years ago
7.0 kB
9
Indexable
from cleantext import clean
import re
def clean_text(text):
text = clean(
text,
fix_unicode=True, # Исправление юникода
to_ascii=False, # Отключаем транслитерацию в ASCII
lower=True, # Приведение к нижнему регистру
no_line_breaks=True, # Удаление переносов строк
no_urls=True, # Удаление URL, замена на ''
no_emails=True, # Удаление email, замена на ''
no_phone_numbers=True, # Удаление телефонных номеров, замена на ''
no_numbers=False, # Оставляем числа (если они важны)
no_digits=True, # Оставляем цифры (если они важны)
no_currency_symbols=True, # Удаление символов валют (при необходимости), замена на ''
no_punct=True, # Удаление пунктуации
no_emoji=True, # Удаление всех эмодзи
replace_with_url="", # Не заменяем URL на шаблонное слово
replace_with_email="", # Не заменяем email на шаблонное слово
replace_with_phone_number="", # Не заменяем телефонные номера на шаблонное слово
replace_with_digit="",
lang="ru", # Язык текста - русский
)
text = re.sub(r'►|---', '', text)
return text
data['описание_канала'] = data['описание_канала'].apply(clean_text)
data['Названия_видео_роликов'] = data['Названия_видео_роликов'].apply(clean_text)
data['метка_класса'] = data['метка_класса'].apply(lambda x: x.split(', ') if isinstance(x, str) else [])
all_classes = set([cls for sublist in data['метка_класса'] for cls in sublist])
unique_classes = list(all_classes)
class_to_index = {classname: index for index, classname in enumerate(unique_classes)}
data['метка_класса_id'] = data['метка_класса'].apply(
lambda classes: [
class_to_index[cls]
for cls in classes
if cls in class_to_index
]
)
data['combined_text'] = data['название_канала'] + ' ' + data['описание_канала'] + ' ' + data['Названия_видео_роликов']
nan_rows = data[data['название_канала'].isna() | data['описание_канала'].isna() | data['Названия_видео_роликов'].isna()]
data_cleaned = data.dropna(subset=['название_канала', 'описание_канала', 'Названия_видео_роликов'])
print(f"Размер оригинального датасета: {data.shape}")
print(f"Размер очищенного датасета: {data_cleaned.shape}")
data = data_cleaned
_______________________________________________________________________________________
ТОКЕНИЗАЦИЯ
_______________________________________________________________________________________
from transformers import BertTokenizer
from sklearn.preprocessing import MultiLabelBinarizer
from torch.utils.data import Dataset, DataLoader, random_split
class CustomDataset(Dataset):
def __init__(self, texts, labels, tokenizer, max_length=512):
self.tokenizer = tokenizer
self.texts = texts
self.labels = labels
self.max_length = max_length
def __len__(self):
return len(self.texts)
def __getitem__(self, idx):
text = self.texts[idx]
labels = self.labels[idx]
encoding = self.tokenizer.encode_plus(
text,
add_special_tokens=True,
max_length=self.max_length,
padding="max_length",
truncation=True,
return_attention_mask=True,
return_tensors='pt',
)
return {
'input_ids': encoding['input_ids'].flatten(),
'attention_mask': encoding['attention_mask'].flatten(),
'labels': torch.tensor(labels, dtype=torch.float)
}
tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-cased')
mlb = MultiLabelBinarizer()
labels_one_hot = mlb.fit_transform(data['метка_класса_id'].values)
dataset = CustomDataset(data['combined_text'].values, labels_one_hot, tokenizer)
train_size = int(0.9 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
train_dataloader = DataLoader(train_dataset, shuffle=True)
val_dataloader = DataLoader(val_dataset)
________________________________________________________________________________________
ОБУЧЕНИЕ
_______________________________________________________________________________________
from transformers import Trainer, TrainingArguments, BertForSequenceClassification
from transformers import BertTokenizerFast
from sklearn.metrics import accuracy_score, precision_recall_fscore_support
import torch
tokenizer = BertTokenizerFast.from_pretrained('bert-base-multilingual-cased')
def compute_metrics(eval_pred):
logits, labels = eval_pred
# Преобразование логитов в вероятности с помощью сигмоиды
probabilities = torch.sigmoid(torch.tensor(logits)).numpy()
# Преобразование вероятностей в бинарные предсказания
predictions = (probabilities > 0.5).astype(int)
# Вычисление метрик для каждого класса и усреднение
precision, recall, f1, _ = precision_recall_fscore_support(labels, predictions, average='micro')
acc = accuracy_score(labels, predictions)
return {'accuracy': acc, 'f1': f1, 'precision': precision, 'recall': recall}
training_args = TrainingArguments(
output_dir='./results',
num_train_epochs=5,
per_device_train_batch_size=16,
per_device_eval_batch_size=16,
warmup_steps=500,
weight_decay=0.01,
logging_dir='./logs',
logging_steps=10,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
metric_for_best_model="f1",
)
model = BertForSequenceClassification.from_pretrained(
'bert-base-multilingual-cased',
problem_type="multi_label_classification",
num_labels=len(unique_classes)
)
model.to(torch.device("cuda" if torch.cuda.is_available() else "cpu"))
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=val_dataset,
compute_metrics=compute_metrics,
)
trainer.train()
# id2label = {str(index): label for label, index in class_to_index.items()}
# label2id = {label: str(index) for label, index in class_to_index.items()}
# model.config.id2label = id2label
# model.config.label2id = label2id
trainer.save_model("./best_model")Editor is loading...
Leave a Comment