marcoorasch commited on
Commit
7c07f27
·
verified ·
1 Parent(s): 8437c36

Upload 3 files

Browse files
Hatespeech_Offensive_Classification_llama3.2-3B-instruct.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
Hatespeech_Offensive_Classification_testmodels.ipynb ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "93f5db97-0d94-4464-9891-0ebfe519d534",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "#!pip install -U bitsandbytes\n",
11
+ "#!pip install -U transformers\n",
12
+ "#!pip install -U accelerate\n",
13
+ "#!pip install -U peft\n",
14
+ "#!pip install -U trl"
15
+ ]
16
+ },
17
+ {
18
+ "cell_type": "code",
19
+ "execution_count": null,
20
+ "id": "1fd5f7f5-c053-4ecd-a0d4-b7a12ee32136",
21
+ "metadata": {},
22
+ "outputs": [],
23
+ "source": [
24
+ "#!huggingface-cli whoami"
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "code",
29
+ "execution_count": null,
30
+ "id": "5780dde2-c61e-464b-91aa-e68301124b6e",
31
+ "metadata": {},
32
+ "outputs": [],
33
+ "source": [
34
+ "import numpy as np\n",
35
+ "import pandas as pd\n",
36
+ "import os\n",
37
+ "from tqdm import tqdm\n",
38
+ "import bitsandbytes as bnb\n",
39
+ "import torch\n",
40
+ "import torch.nn as nn\n",
41
+ "import transformers\n",
42
+ "from datasets import Dataset\n",
43
+ "from peft import LoraConfig, PeftConfig\n",
44
+ "from trl import SFTTrainer\n",
45
+ "from trl import setup_chat_format\n",
46
+ "from transformers import (AutoModelForCausalLM, \n",
47
+ " AutoTokenizer, \n",
48
+ " BitsAndBytesConfig, \n",
49
+ " TrainingArguments, \n",
50
+ " pipeline, \n",
51
+ " logging)\n",
52
+ "from sklearn.metrics import (accuracy_score, \n",
53
+ " classification_report, \n",
54
+ " confusion_matrix)\n",
55
+ "from sklearn.model_selection import train_test_split"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": null,
61
+ "id": "84b29425-b5ad-4852-b9e2-6887eece0de8",
62
+ "metadata": {},
63
+ "outputs": [],
64
+ "source": [
65
+ "from datasets import load_dataset\n",
66
+ "\n",
67
+ "df = pd.read_parquet(\"hf://datasets/tdavidson/hate_speech_offensive/data/train-00000-of-00001.parquet\")\n",
68
+ "df.head()"
69
+ ]
70
+ },
71
+ {
72
+ "cell_type": "code",
73
+ "execution_count": null,
74
+ "id": "b7395daa-b933-4204-854c-472548343f31",
75
+ "metadata": {},
76
+ "outputs": [],
77
+ "source": [
78
+ "df = df.rename(columns={\"class\": \"label\",\"tweet\": \"text\"}).sample(frac=1, random_state=85).reset_index(drop=True).head(3000)\n",
79
+ "df.loc[:,'label'] = df.loc[:,'label'].replace(0,'Hate')\n",
80
+ "df.loc[:,'label'] = df.loc[:,'label'].replace(1,'Offensive')\n",
81
+ "df.loc[:,'label'] = df.loc[:,'label'].replace(2,'Normal')\n",
82
+ "# Split the DataFrame\n",
83
+ "train_size = 0.8\n",
84
+ "eval_size = 0.1\n",
85
+ "\n",
86
+ "# Calculate sizes\n",
87
+ "train_end = int(train_size * len(df))\n",
88
+ "eval_end = train_end + int(eval_size * len(df))\n",
89
+ "\n",
90
+ "# Split the data\n",
91
+ "X_train = df[:train_end]\n",
92
+ "X_eval = df[train_end:eval_end]\n",
93
+ "X_test = df[eval_end:]\n",
94
+ "# Define the prompt generation functions\n",
95
+ "def generate_prompt(data_point):\n",
96
+ " return f\"\"\"\n",
97
+ " Classify the text into Hatespeech, Offensive, Normal and return the answer as the corresponding label.\n",
98
+ "text: {data_point[\"text\"]}\n",
99
+ "label: {data_point[\"label\"]}\"\"\".strip()\n",
100
+ "\n",
101
+ "def generate_test_prompt(data_point):\n",
102
+ " return f\"\"\"\n",
103
+ " Classify the text into Hatespeech, Offensive, Normal and return the answer as the corresponding label.\n",
104
+ " text: {data_point[\"text\"]}\n",
105
+ " label: \"\"\".strip()\n",
106
+ "\n",
107
+ "# Generate prompts for training and evaluation data\n",
108
+ "X_train.loc[:,'text'] = X_train.apply(generate_prompt, axis=1)\n",
109
+ "X_eval.loc[:,'text'] = X_eval.apply(generate_prompt, axis=1)\n",
110
+ "\n",
111
+ "# Generate test prompts and extract true labels\n",
112
+ "y_true = X_test.loc[:,'label']\n",
113
+ "X_test = pd.DataFrame(X_test.apply(generate_test_prompt, axis=1), columns=[\"text\"])"
114
+ ]
115
+ },
116
+ {
117
+ "cell_type": "code",
118
+ "execution_count": null,
119
+ "id": "bc18edca-e02b-4a32-8cc1-7d83f00bdba5",
120
+ "metadata": {},
121
+ "outputs": [],
122
+ "source": [
123
+ "X_train.label.value_counts()"
124
+ ]
125
+ },
126
+ {
127
+ "cell_type": "code",
128
+ "execution_count": null,
129
+ "id": "52d5ccf5-7669-447f-8a90-43cbb7e8e337",
130
+ "metadata": {},
131
+ "outputs": [],
132
+ "source": [
133
+ "train_data = Dataset.from_pandas(X_train[[\"text\"]])\n",
134
+ "eval_data = Dataset.from_pandas(X_eval[[\"text\"]])"
135
+ ]
136
+ },
137
+ {
138
+ "cell_type": "code",
139
+ "execution_count": null,
140
+ "id": "f7732c58-e8c6-436b-810d-40abd4f593ab",
141
+ "metadata": {},
142
+ "outputs": [],
143
+ "source": [
144
+ "train_data['text'][2000]"
145
+ ]
146
+ },
147
+ {
148
+ "cell_type": "code",
149
+ "execution_count": null,
150
+ "id": "0f15e59f-9e50-48f1-b6f5-d6dc46db623f",
151
+ "metadata": {},
152
+ "outputs": [],
153
+ "source": [
154
+ "#CHANGE MODEL HERE#\n",
155
+ "base_model_name = \"meta-llama/Llama-3.2-3B-Instruct\"\n",
156
+ "\n",
157
+ "bnb_config = BitsAndBytesConfig(\n",
158
+ " load_in_4bit=True,\n",
159
+ " bnb_4bit_use_double_quant=False,\n",
160
+ " bnb_4bit_quant_type=\"nf4\",\n",
161
+ " bnb_4bit_compute_dtype=\"float16\",\n",
162
+ ")\n",
163
+ "\n",
164
+ "model = AutoModelForCausalLM.from_pretrained(\n",
165
+ " base_model_name,\n",
166
+ " device_map=\"auto\",\n",
167
+ " torch_dtype=\"float16\",\n",
168
+ " quantization_config=bnb_config, \n",
169
+ ")\n",
170
+ "\n",
171
+ "model.config.use_cache = False\n",
172
+ "model.config.pretraining_tp = 1\n",
173
+ "\n",
174
+ "tokenizer = AutoTokenizer.from_pretrained(base_model_name)\n",
175
+ "\n",
176
+ "tokenizer.pad_token_id = tokenizer.eos_token_id"
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": null,
182
+ "id": "97ccf698-09de-4423-9287-8dedf779fc3d",
183
+ "metadata": {},
184
+ "outputs": [],
185
+ "source": [
186
+ "def predict(test, model, tokenizer):\n",
187
+ " y_pred = []\n",
188
+ " labels = [\"Hate\", \"Offensive\", \"Normal\"]\n",
189
+ " \n",
190
+ " for i in tqdm(range(len(test))):\n",
191
+ " prompt = test.iloc[i][\"text\"]\n",
192
+ " pipe = pipeline(task=\"text-generation\", \n",
193
+ " model=model, \n",
194
+ " tokenizer=tokenizer, \n",
195
+ " max_new_tokens=2, \n",
196
+ " temperature=0.1)\n",
197
+ " \n",
198
+ " result = pipe(prompt)\n",
199
+ " answer = result[0]['generated_text'].split(\"label:\")[-1].strip()\n",
200
+ " \n",
201
+ " # Determine the predicted category\n",
202
+ " for label in labels:\n",
203
+ " if label.lower() in answer.lower():\n",
204
+ " y_pred.append(label)\n",
205
+ " break\n",
206
+ " else:\n",
207
+ " y_pred.append(\"none\")\n",
208
+ " \n",
209
+ " return y_pred\n",
210
+ "\n",
211
+ "y_pred = predict(X_test, model, tokenizer)"
212
+ ]
213
+ },
214
+ {
215
+ "cell_type": "code",
216
+ "execution_count": null,
217
+ "id": "2bc4f2ea-5cde-4368-8f92-7883995d8977",
218
+ "metadata": {},
219
+ "outputs": [],
220
+ "source": [
221
+ "def evaluate(y_true, y_pred):\n",
222
+ " labels = [\"Hate\", \"Offensive\", \"Normal\"]\n",
223
+ " mapping = {label: idx for idx, label in enumerate(labels)}\n",
224
+ " \n",
225
+ " def map_func(x):\n",
226
+ " return mapping.get(x, -1) # Map to -1 if not found, but should not occur with correct data\n",
227
+ " \n",
228
+ " y_true_mapped = np.vectorize(map_func)(y_true)\n",
229
+ " y_pred_mapped = np.vectorize(map_func)(y_pred)\n",
230
+ " \n",
231
+ " # Calculate accuracy\n",
232
+ " accuracy = accuracy_score(y_true=y_true_mapped, y_pred=y_pred_mapped)\n",
233
+ " print(f'Accuracy: {accuracy:.3f}')\n",
234
+ " \n",
235
+ " # Generate accuracy report\n",
236
+ " unique_labels = set(y_true_mapped) # Get unique labels\n",
237
+ " \n",
238
+ " for label in unique_labels:\n",
239
+ " label_indices = [i for i in range(len(y_true_mapped)) if y_true_mapped[i] == label]\n",
240
+ " label_y_true = [y_true_mapped[i] for i in label_indices]\n",
241
+ " label_y_pred = [y_pred_mapped[i] for i in label_indices]\n",
242
+ " label_accuracy = accuracy_score(label_y_true, label_y_pred)\n",
243
+ " print(f'Accuracy for label {labels[label]}: {label_accuracy:.3f}')\n",
244
+ " \n",
245
+ " # Generate classification report\n",
246
+ " class_report = classification_report(y_true=y_true_mapped, y_pred=y_pred_mapped, target_names=labels, labels=list(range(len(labels))))\n",
247
+ " print('\\nClassification Report:')\n",
248
+ " print(class_report)\n",
249
+ " \n",
250
+ " # Generate confusion matrix\n",
251
+ " conf_matrix = confusion_matrix(y_true=y_true_mapped, y_pred=y_pred_mapped, labels=list(range(len(labels))))\n",
252
+ " print('\\nConfusion Matrix:')\n",
253
+ " print(conf_matrix)\n",
254
+ "\n",
255
+ "evaluate(y_true, y_pred)"
256
+ ]
257
+ }
258
+ ],
259
+ "metadata": {
260
+ "kernelspec": {
261
+ "display_name": "Python 3 (ipykernel)",
262
+ "language": "python",
263
+ "name": "python3"
264
+ },
265
+ "language_info": {
266
+ "codemirror_mode": {
267
+ "name": "ipython",
268
+ "version": 3
269
+ },
270
+ "file_extension": ".py",
271
+ "mimetype": "text/x-python",
272
+ "name": "python",
273
+ "nbconvert_exporter": "python",
274
+ "pygments_lexer": "ipython3",
275
+ "version": "3.12.5"
276
+ }
277
+ },
278
+ "nbformat": 4,
279
+ "nbformat_minor": 5
280
+ }
run.ipynb ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 31,
6
+ "id": "b368a208-7b0f-4928-aad6-94030a47d573",
7
+ "metadata": {},
8
+ "outputs": [
9
+ {
10
+ "data": {
11
+ "application/vnd.jupyter.widget-view+json": {
12
+ "model_id": "6d72bc7458d64ec7af180321e7d9d7aa",
13
+ "version_major": 2,
14
+ "version_minor": 0
15
+ },
16
+ "text/plain": [
17
+ "Loading checkpoint shards: 0%| | 0/2 [00:00<?, ?it/s]"
18
+ ]
19
+ },
20
+ "metadata": {},
21
+ "output_type": "display_data"
22
+ }
23
+ ],
24
+ "source": [
25
+ "###load models\n",
26
+ "base_model = \"meta-llama/Llama-3.2-3B-Instruct\"\n",
27
+ "fine_tuned_model = \"/home/marco/llama-3.2-instruct-offensive-classification-1.0.0\"\n",
28
+ "\n",
29
+ "from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline\n",
30
+ "from peft import PeftModel\n",
31
+ "import torch\n",
32
+ "\n",
33
+ "\n",
34
+ "# Reload tokenizer and model\n",
35
+ "tokenizer = AutoTokenizer.from_pretrained(fine_tuned_model)\n",
36
+ "\n",
37
+ "model = AutoModelForCausalLM.from_pretrained(\n",
38
+ " fine_tuned_model,\n",
39
+ " return_dict=True,\n",
40
+ " low_cpu_mem_usage=True,\n",
41
+ " torch_dtype=torch.float16,\n",
42
+ " device_map=\"auto\",\n",
43
+ " trust_remote_code=True,\n",
44
+ " offload_buffers=True\n",
45
+ ")"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": 32,
51
+ "id": "54e39123-1ed6-4990-8295-6df1e0563fc5",
52
+ "metadata": {},
53
+ "outputs": [],
54
+ "source": [
55
+ "text = \"You are a pig!\""
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": 33,
61
+ "id": "1b68121f-3215-46f6-901b-406be4e05a06",
62
+ "metadata": {},
63
+ "outputs": [
64
+ {
65
+ "name": "stderr",
66
+ "output_type": "stream",
67
+ "text": [
68
+ "Device set to use cpu\n"
69
+ ]
70
+ },
71
+ {
72
+ "name": "stdout",
73
+ "output_type": "stream",
74
+ "text": [
75
+ "Offensive\n"
76
+ ]
77
+ }
78
+ ],
79
+ "source": [
80
+ "###Start Prompt\n",
81
+ "prompt = f\"\"\"Classify the text into Hatespeech, Offensive, Normal and return the answer as the corresponding label.\n",
82
+ "text: {text}\n",
83
+ "label: \"\"\".strip()\n",
84
+ "\n",
85
+ "pipe = pipeline(\n",
86
+ " \"text-generation\",\n",
87
+ " model=model,\n",
88
+ " tokenizer=tokenizer,\n",
89
+ " torch_dtype=torch.float16,\n",
90
+ " device_map=\"auto\"\n",
91
+ ")\n",
92
+ "\n",
93
+ "outputs = pipe(prompt, max_new_tokens=2, do_sample=True, temperature=0.1, pad_token_id=tokenizer.eos_token_id)\n",
94
+ "print(outputs[0][\"generated_text\"].split(\"label: \")[-1].strip())"
95
+ ]
96
+ },
97
+ {
98
+ "cell_type": "code",
99
+ "execution_count": null,
100
+ "id": "d709317d-b9cf-4590-9caf-ac74842f6be2",
101
+ "metadata": {},
102
+ "outputs": [],
103
+ "source": []
104
+ }
105
+ ],
106
+ "metadata": {
107
+ "kernelspec": {
108
+ "display_name": "Python 3 (ipykernel)",
109
+ "language": "python",
110
+ "name": "python3"
111
+ },
112
+ "language_info": {
113
+ "codemirror_mode": {
114
+ "name": "ipython",
115
+ "version": 3
116
+ },
117
+ "file_extension": ".py",
118
+ "mimetype": "text/x-python",
119
+ "name": "python",
120
+ "nbconvert_exporter": "python",
121
+ "pygments_lexer": "ipython3",
122
+ "version": "3.12.5"
123
+ }
124
+ },
125
+ "nbformat": 4,
126
+ "nbformat_minor": 5
127
+ }