jatinmehra commited on
Commit
5584c5d
1 Parent(s): 942fa87
README.md CHANGED
@@ -1,3 +1,72 @@
1
  ---
2
  license: mit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  license: mit
3
+ datasets:
4
+ - nvidia/HelpSteer2
5
+ language:
6
+ - en
7
+ metrics:
8
+ - accuracy
9
+ - f1
10
+ - recall
11
+ base_model:
12
+ - HuggingFaceTB/SmolLM2-135M-Instruct
13
+ new_version: jatinmehra/smolLM-fined-tuned-for-PLAGAIRISM-Detection
14
+ pipeline_tag: text-classification
15
+ library_name: transformers
16
+ tags:
17
+ - legal
18
+ - plagiarism-detection
19
  ---
20
+ # SmolLM Fine-Tuned for Plagiarism Detection
21
+
22
+ This repository hosts a fine-tuned version of SmolLM (135M Parameters) for detecting plagiarism by classifying sentence pairs as either plagiarized or non-plagiarized. Fine-tuning was performed on the [MIT Plagiarism Detection Dataset](https://www.kaggle.com/datasets/ruvelpereira/mit-plagairism-detection-dataset) to enhance the model’s accuracy and performance in identifying textual similarities.
23
+
24
+ ## Model Information
25
+
26
+ - **Base Model**: HuggingFaceTB/SmolLM2-135M-Instruct
27
+ - **Fine-tuned Model Name**: `jatinmehra/smolLM-fine-tuned-for-plagiarism-detection`
28
+ - **License**: MIT
29
+ - **Language**: English
30
+ - **Task**: Text Classification
31
+ - **Metrics**: Accuracy, F1 Score, Recall
32
+
33
+ ## Dataset
34
+
35
+ The model was fine-tuned on the MIT Plagiarism Detection Dataset, which provides pairs of sentences labeled to indicate whether one is a rephrased version of the other (i.e., plagiarized). This dataset is suited for sentence-level similarity detection, and the labels (`1` for plagiarized and `0` for non-plagiarized) offer a straightforward approach to training for binary classification.
36
+
37
+ ## Training Procedure
38
+
39
+ The fine-tuning was done using the `transformers` library from Hugging Face. Key details include:
40
+
41
+ - **Model Architecture**: The model was modified for sequence classification with two output labels.
42
+ - **Optimizer**: AdamW was used to handle optimization, with a learning rate of 2e-5.
43
+ - **Loss Function**: Cross-Entropy Loss was used as the objective function.
44
+ - **Batch Size**: Set to 16 for memory and performance balance.
45
+ - **Epochs**: Trained for 3 epochs.
46
+ - **Padding**: A custom padding token was added to align with SmolLM’s requirements, ensuring smooth tokenization.
47
+
48
+ Training involved a DataLoader that fed sentence pairs into the model, tokenized with attention masking, truncation, and padding. After training, the model achieved a high accuracy score, around 99.66% on the training dataset.
49
+
50
+ ## Usage
51
+
52
+ This model can be employed directly within the Hugging Face Transformers library to classify sentence pairs as plagiarized or non-plagiarized. Simply load the model and tokenizer from the `jatinmehra/smolLM-fine-tuned-for-plagiarism-detection` repository, and provide sentence pairs as inputs. The model’s output logits can be interpreted to determine whether plagiarism is detected.
53
+
54
+ ## Evaluation
55
+
56
+ During evaluation, the model performed robustly with the following metrics:
57
+
58
+ - **Accuracy**: Approximately **99.66%** on the training set | **100%** on test set
59
+ - **Other Metrics**: f1: **1.0** recall: **1.0**
60
+
61
+ ## Model and Tokenizer Saving
62
+
63
+ Upon completion of fine-tuning, the model and tokenizer were saved for deployment and ease of loading in future projects. They can be loaded from Hugging Face or saved locally for custom applications.
64
+
65
+ ## License
66
+
67
+ This model and associated code are released under the MIT License, allowing for both personal and commercial use.
68
+
69
+ ### Connect with Me
70
+
71
+ I appreciate your support and am happy to connect!
72
+ [GitHub](https://github.com/Jatin-Mehra119) | [Email]([email protected]) | [LinkedIn](https://www.linkedin.com/in/jatin-mehra119/) | [Portfolio](https://jatin-mehra119.github.io/Profile/)
app.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import torch
3
+ from transformers import GPT2Tokenizer, LlamaForSequenceClassification
4
+ import fitz # PyMuPDF for extracting text from PDFs
5
+ import io
6
+ from torch.utils.data import Dataset
7
+ from sklearn.metrics import classification_report
8
+
9
+ # Load the tokenizer and model
10
+ model_path = "model"
11
+ tokenizer = GPT2Tokenizer.from_pretrained(model_path, local_files_only=True)
12
+ model = LlamaForSequenceClassification.from_pretrained(model_path, local_files_only=True)
13
+ model.eval()
14
+
15
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
16
+ model = model.to(device)
17
+
18
+ # Function to extract text from a PDF
19
+ def extract_text_from_pdf(pdf_file):
20
+ # Read the PDF file as a binary stream
21
+ pdf_bytes = pdf_file.read()
22
+
23
+ # Using BytesIO to convert the binary data into a file-like object
24
+ pdf_stream = io.BytesIO(pdf_bytes)
25
+
26
+ # Open the PDF using PyMuPDF from the file-like object
27
+ doc = fitz.open(stream=pdf_stream, filetype="pdf")
28
+
29
+ text = ""
30
+ for page in doc:
31
+ text += page.get_text("text")
32
+
33
+ return text
34
+
35
+ # Function to preprocess and tokenize the input text
36
+ def preprocess_text(text1, text2):
37
+ inputs = tokenizer(
38
+ text1, text2,
39
+ add_special_tokens=True,
40
+ max_length=128,
41
+ padding='max_length',
42
+ truncation=True,
43
+ return_tensors="pt"
44
+ )
45
+ return inputs
46
+
47
+ # Dataset class (similar to your existing one)
48
+ class PlagiarismDataset(Dataset):
49
+ def __init__(self, text1, text2, tokenizer):
50
+ self.text1 = text1
51
+ self.text2 = text2
52
+ self.tokenizer = tokenizer
53
+
54
+ def __len__(self):
55
+ return len(self.text1)
56
+
57
+ def __getitem__(self, idx):
58
+ inputs = preprocess_text(self.text1[idx], self.text2[idx])
59
+ return {
60
+ 'input_ids': inputs['input_ids'].squeeze(0),
61
+ 'attention_mask': inputs['attention_mask'].squeeze(0)
62
+ }
63
+
64
+ # Function to detect plagiarism using the model
65
+ def detect_plagiarism(text1, text2):
66
+ dataset = PlagiarismDataset(text1, text2, tokenizer)
67
+ data_loader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False)
68
+
69
+ predictions = []
70
+ with torch.no_grad():
71
+ for batch in data_loader:
72
+ input_ids = batch['input_ids'].to(device)
73
+ attention_mask = batch['attention_mask'].to(device)
74
+
75
+ outputs = model(input_ids=input_ids, attention_mask=attention_mask)
76
+ preds = torch.argmax(outputs.logits, dim=1)
77
+
78
+ predictions.append(preds.item())
79
+
80
+ return predictions[0]
81
+
82
+ # Streamlit UI
83
+ st.title("Plagiarism Detection using LLM")
84
+ st.write("Upload two PDFs for plagiarism detection.")
85
+
86
+ # Upload PDFs
87
+ pdf_file1 = st.file_uploader("Upload the first PDF", type="pdf")
88
+ pdf_file2 = st.file_uploader("Upload the second PDF", type="pdf")
89
+
90
+ if pdf_file1 and pdf_file2:
91
+ # Extract text from PDFs
92
+ text1 = extract_text_from_pdf(pdf_file1)
93
+ text2 = extract_text_from_pdf(pdf_file2)
94
+
95
+ # Display some text from the PDFs for context
96
+ st.subheader("Text from the first document:")
97
+ st.text(text1[:1000]) # Display the first 1000 characters of the document
98
+ st.subheader("Text from the second document:")
99
+ st.text(text2[:1000])
100
+
101
+ # Detect plagiarism
102
+ result = detect_plagiarism([text1], [text2])
103
+
104
+ # Display the result
105
+ if result == 1:
106
+ st.success("Plagiarism detected!")
107
+ else:
108
+ st.success("No plagiarism detected.")
model/added_tokens.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "[PAD]": 49152
3
+ }
model/config.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "HuggingFaceTB/SmolLM-135M",
3
+ "architectures": [
4
+ "LlamaForSequenceClassification"
5
+ ],
6
+ "attention_bias": false,
7
+ "attention_dropout": 0.0,
8
+ "bos_token_id": 0,
9
+ "eos_token_id": 0,
10
+ "head_dim": 64,
11
+ "hidden_act": "silu",
12
+ "hidden_size": 576,
13
+ "initializer_range": 0.02,
14
+ "intermediate_size": 1536,
15
+ "max_position_embeddings": 2048,
16
+ "mlp_bias": false,
17
+ "model_type": "llama",
18
+ "num_attention_heads": 9,
19
+ "num_hidden_layers": 30,
20
+ "num_key_value_heads": 3,
21
+ "pad_token_id": 49152,
22
+ "pretraining_tp": 1,
23
+ "rms_norm_eps": 1e-05,
24
+ "rope_scaling": null,
25
+ "rope_theta": 10000.0,
26
+ "tie_word_embeddings": true,
27
+ "torch_dtype": "float32",
28
+ "transformers_version": "4.45.1",
29
+ "use_cache": true,
30
+ "vocab_size": 49153
31
+ }
model/merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
model/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:037f0e1d8903ff226c57c41d8419a5fa9648f7d50e9d093d5bc571139762b30e
3
+ size 538097400
model/special_tokens_map.json ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "additional_special_tokens": [
3
+ "<|endoftext|>",
4
+ "<|im_start|>",
5
+ "<|im_end|>",
6
+ "<repo_name>",
7
+ "<reponame>",
8
+ "<file_sep>",
9
+ "<filename>",
10
+ "<gh_stars>",
11
+ "<issue_start>",
12
+ "<issue_comment>",
13
+ "<issue_closed>",
14
+ "<jupyter_start>",
15
+ "<jupyter_text>",
16
+ "<jupyter_code>",
17
+ "<jupyter_output>",
18
+ "<jupyter_script>",
19
+ "<empty_output>"
20
+ ],
21
+ "bos_token": {
22
+ "content": "<|endoftext|>",
23
+ "lstrip": false,
24
+ "normalized": false,
25
+ "rstrip": false,
26
+ "single_word": false
27
+ },
28
+ "eos_token": {
29
+ "content": "<|endoftext|>",
30
+ "lstrip": false,
31
+ "normalized": false,
32
+ "rstrip": false,
33
+ "single_word": false
34
+ },
35
+ "pad_token": {
36
+ "content": "[PAD]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false
41
+ },
42
+ "unk_token": {
43
+ "content": "<|endoftext|>",
44
+ "lstrip": false,
45
+ "normalized": false,
46
+ "rstrip": false,
47
+ "single_word": false
48
+ }
49
+ }
model/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
model/tokenizer_config.json ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "added_tokens_decoder": {
4
+ "0": {
5
+ "content": "<|endoftext|>",
6
+ "lstrip": false,
7
+ "normalized": false,
8
+ "rstrip": false,
9
+ "single_word": false,
10
+ "special": true
11
+ },
12
+ "1": {
13
+ "content": "<|im_start|>",
14
+ "lstrip": false,
15
+ "normalized": false,
16
+ "rstrip": false,
17
+ "single_word": false,
18
+ "special": true
19
+ },
20
+ "2": {
21
+ "content": "<|im_end|>",
22
+ "lstrip": false,
23
+ "normalized": false,
24
+ "rstrip": false,
25
+ "single_word": false,
26
+ "special": true
27
+ },
28
+ "3": {
29
+ "content": "<repo_name>",
30
+ "lstrip": false,
31
+ "normalized": false,
32
+ "rstrip": false,
33
+ "single_word": false,
34
+ "special": true
35
+ },
36
+ "4": {
37
+ "content": "<reponame>",
38
+ "lstrip": false,
39
+ "normalized": false,
40
+ "rstrip": false,
41
+ "single_word": false,
42
+ "special": true
43
+ },
44
+ "5": {
45
+ "content": "<file_sep>",
46
+ "lstrip": false,
47
+ "normalized": false,
48
+ "rstrip": false,
49
+ "single_word": false,
50
+ "special": true
51
+ },
52
+ "6": {
53
+ "content": "<filename>",
54
+ "lstrip": false,
55
+ "normalized": false,
56
+ "rstrip": false,
57
+ "single_word": false,
58
+ "special": true
59
+ },
60
+ "7": {
61
+ "content": "<gh_stars>",
62
+ "lstrip": false,
63
+ "normalized": false,
64
+ "rstrip": false,
65
+ "single_word": false,
66
+ "special": true
67
+ },
68
+ "8": {
69
+ "content": "<issue_start>",
70
+ "lstrip": false,
71
+ "normalized": false,
72
+ "rstrip": false,
73
+ "single_word": false,
74
+ "special": true
75
+ },
76
+ "9": {
77
+ "content": "<issue_comment>",
78
+ "lstrip": false,
79
+ "normalized": false,
80
+ "rstrip": false,
81
+ "single_word": false,
82
+ "special": true
83
+ },
84
+ "10": {
85
+ "content": "<issue_closed>",
86
+ "lstrip": false,
87
+ "normalized": false,
88
+ "rstrip": false,
89
+ "single_word": false,
90
+ "special": true
91
+ },
92
+ "11": {
93
+ "content": "<jupyter_start>",
94
+ "lstrip": false,
95
+ "normalized": false,
96
+ "rstrip": false,
97
+ "single_word": false,
98
+ "special": true
99
+ },
100
+ "12": {
101
+ "content": "<jupyter_text>",
102
+ "lstrip": false,
103
+ "normalized": false,
104
+ "rstrip": false,
105
+ "single_word": false,
106
+ "special": true
107
+ },
108
+ "13": {
109
+ "content": "<jupyter_code>",
110
+ "lstrip": false,
111
+ "normalized": false,
112
+ "rstrip": false,
113
+ "single_word": false,
114
+ "special": true
115
+ },
116
+ "14": {
117
+ "content": "<jupyter_output>",
118
+ "lstrip": false,
119
+ "normalized": false,
120
+ "rstrip": false,
121
+ "single_word": false,
122
+ "special": true
123
+ },
124
+ "15": {
125
+ "content": "<jupyter_script>",
126
+ "lstrip": false,
127
+ "normalized": false,
128
+ "rstrip": false,
129
+ "single_word": false,
130
+ "special": true
131
+ },
132
+ "16": {
133
+ "content": "<empty_output>",
134
+ "lstrip": false,
135
+ "normalized": false,
136
+ "rstrip": false,
137
+ "single_word": false,
138
+ "special": true
139
+ },
140
+ "49152": {
141
+ "content": "[PAD]",
142
+ "lstrip": false,
143
+ "normalized": false,
144
+ "rstrip": false,
145
+ "single_word": false,
146
+ "special": true
147
+ }
148
+ },
149
+ "additional_special_tokens": [
150
+ "<|endoftext|>",
151
+ "<|im_start|>",
152
+ "<|im_end|>",
153
+ "<repo_name>",
154
+ "<reponame>",
155
+ "<file_sep>",
156
+ "<filename>",
157
+ "<gh_stars>",
158
+ "<issue_start>",
159
+ "<issue_comment>",
160
+ "<issue_closed>",
161
+ "<jupyter_start>",
162
+ "<jupyter_text>",
163
+ "<jupyter_code>",
164
+ "<jupyter_output>",
165
+ "<jupyter_script>",
166
+ "<empty_output>"
167
+ ],
168
+ "bos_token": "<|endoftext|>",
169
+ "clean_up_tokenization_spaces": false,
170
+ "eos_token": "<|endoftext|>",
171
+ "model_max_length": 1000000000000000019884624838656,
172
+ "pad_token": "[PAD]",
173
+ "tokenizer_class": "GPT2Tokenizer",
174
+ "unk_token": "<|endoftext|>",
175
+ "vocab_size": 49152
176
+ }
model/vocab.json ADDED
The diff for this file is too large to render. See raw diff
 
plagairism-fine-tuning using LLM.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
test-model.ipynb ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {},
7
+ "outputs": [
8
+ {
9
+ "data": {
10
+ "text/plain": [
11
+ "LlamaForSequenceClassification(\n",
12
+ " (model): LlamaModel(\n",
13
+ " (embed_tokens): Embedding(49153, 576, padding_idx=49152)\n",
14
+ " (layers): ModuleList(\n",
15
+ " (0-29): 30 x LlamaDecoderLayer(\n",
16
+ " (self_attn): LlamaSdpaAttention(\n",
17
+ " (q_proj): Linear(in_features=576, out_features=576, bias=False)\n",
18
+ " (k_proj): Linear(in_features=576, out_features=192, bias=False)\n",
19
+ " (v_proj): Linear(in_features=576, out_features=192, bias=False)\n",
20
+ " (o_proj): Linear(in_features=576, out_features=576, bias=False)\n",
21
+ " (rotary_emb): LlamaRotaryEmbedding()\n",
22
+ " )\n",
23
+ " (mlp): LlamaMLP(\n",
24
+ " (gate_proj): Linear(in_features=576, out_features=1536, bias=False)\n",
25
+ " (up_proj): Linear(in_features=576, out_features=1536, bias=False)\n",
26
+ " (down_proj): Linear(in_features=1536, out_features=576, bias=False)\n",
27
+ " (act_fn): SiLU()\n",
28
+ " )\n",
29
+ " (input_layernorm): LlamaRMSNorm((576,), eps=1e-05)\n",
30
+ " (post_attention_layernorm): LlamaRMSNorm((576,), eps=1e-05)\n",
31
+ " )\n",
32
+ " )\n",
33
+ " (norm): LlamaRMSNorm((576,), eps=1e-05)\n",
34
+ " (rotary_emb): LlamaRotaryEmbedding()\n",
35
+ " )\n",
36
+ " (score): Linear(in_features=576, out_features=2, bias=False)\n",
37
+ ")"
38
+ ]
39
+ },
40
+ "execution_count": 1,
41
+ "metadata": {},
42
+ "output_type": "execute_result"
43
+ }
44
+ ],
45
+ "source": [
46
+ "from transformers import GPT2Tokenizer, LlamaForSequenceClassification\n",
47
+ "\n",
48
+ "# Load the GPT2 tokenizer and Llama model for sequence classification\n",
49
+ "model_path = r\"C:\\Users\\jatin\\OneDrive\\Desktop\\plagiarism-detection\\smolLM-fined-tuned-for-PLAGAIRISM-Detection\\model\"\n",
50
+ "tokenizer = GPT2Tokenizer.from_pretrained(model_path, local_files_only=True)\n",
51
+ "model = LlamaForSequenceClassification.from_pretrained(model_path, local_files_only=True)\n",
52
+ "\n",
53
+ "# Set model to evaluation mode\n",
54
+ "model.eval()"
55
+ ]
56
+ },
57
+ {
58
+ "cell_type": "code",
59
+ "execution_count": 2,
60
+ "metadata": {},
61
+ "outputs": [
62
+ {
63
+ "data": {
64
+ "text/html": [
65
+ "<div>\n",
66
+ "<style scoped>\n",
67
+ " .dataframe tbody tr th:only-of-type {\n",
68
+ " vertical-align: middle;\n",
69
+ " }\n",
70
+ "\n",
71
+ " .dataframe tbody tr th {\n",
72
+ " vertical-align: top;\n",
73
+ " }\n",
74
+ "\n",
75
+ " .dataframe thead th {\n",
76
+ " text-align: right;\n",
77
+ " }\n",
78
+ "</style>\n",
79
+ "<table border=\"1\" class=\"dataframe\">\n",
80
+ " <thead>\n",
81
+ " <tr style=\"text-align: right;\">\n",
82
+ " <th></th>\n",
83
+ " <th>sentence1</th>\n",
84
+ " <th>sentence2</th>\n",
85
+ " <th>label</th>\n",
86
+ " </tr>\n",
87
+ " </thead>\n",
88
+ " <tbody>\n",
89
+ " <tr>\n",
90
+ " <th>0</th>\n",
91
+ " <td>A person on a horse jumps over a broken down a...</td>\n",
92
+ " <td>A person is at a diner, ordering an omelette.</td>\n",
93
+ " <td>0</td>\n",
94
+ " </tr>\n",
95
+ " <tr>\n",
96
+ " <th>1</th>\n",
97
+ " <td>A person on a horse jumps over a broken down a...</td>\n",
98
+ " <td>A person is outdoors, on a horse.</td>\n",
99
+ " <td>1</td>\n",
100
+ " </tr>\n",
101
+ " <tr>\n",
102
+ " <th>2</th>\n",
103
+ " <td>Children smiling and waving at camera</td>\n",
104
+ " <td>There are children present</td>\n",
105
+ " <td>1</td>\n",
106
+ " </tr>\n",
107
+ " <tr>\n",
108
+ " <th>3</th>\n",
109
+ " <td>Children smiling and waving at camera</td>\n",
110
+ " <td>The kids are frowning</td>\n",
111
+ " <td>0</td>\n",
112
+ " </tr>\n",
113
+ " <tr>\n",
114
+ " <th>4</th>\n",
115
+ " <td>A boy is jumping on skateboard in the middle o...</td>\n",
116
+ " <td>The boy skates down the sidewalk.</td>\n",
117
+ " <td>0</td>\n",
118
+ " </tr>\n",
119
+ " </tbody>\n",
120
+ "</table>\n",
121
+ "</div>"
122
+ ],
123
+ "text/plain": [
124
+ " sentence1 \\\n",
125
+ "0 A person on a horse jumps over a broken down a... \n",
126
+ "1 A person on a horse jumps over a broken down a... \n",
127
+ "2 Children smiling and waving at camera \n",
128
+ "3 Children smiling and waving at camera \n",
129
+ "4 A boy is jumping on skateboard in the middle o... \n",
130
+ "\n",
131
+ " sentence2 label \n",
132
+ "0 A person is at a diner, ordering an omelette. 0 \n",
133
+ "1 A person is outdoors, on a horse. 1 \n",
134
+ "2 There are children present 1 \n",
135
+ "3 The kids are frowning 0 \n",
136
+ "4 The boy skates down the sidewalk. 0 "
137
+ ]
138
+ },
139
+ "execution_count": 2,
140
+ "metadata": {},
141
+ "output_type": "execute_result"
142
+ }
143
+ ],
144
+ "source": [
145
+ "import torch\n",
146
+ "import pandas as pd\n",
147
+ "\n",
148
+ "df = pd.read_csv(\"train_snli.txt\", delimiter='\\t', header=None, names=['sentence1', 'sentence2', 'label'])\n",
149
+ "\n",
150
+ "df.head()"
151
+ ]
152
+ },
153
+ {
154
+ "cell_type": "code",
155
+ "execution_count": 3,
156
+ "metadata": {},
157
+ "outputs": [],
158
+ "source": [
159
+ "from torch.utils.data import Dataset, DataLoader\n",
160
+ "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
161
+ "\n",
162
+ "class PlagiarismDataset(Dataset):\n",
163
+ " def __init__(self, df, tokenizer, max_length=128):\n",
164
+ " self.df = df\n",
165
+ " self.tokenizer = tokenizer\n",
166
+ " self.max_length = max_length\n",
167
+ "\n",
168
+ " def __len__(self):\n",
169
+ " return len(self.df)\n",
170
+ "\n",
171
+ " def __getitem__(self, index):\n",
172
+ " row = self.df.iloc[index]\n",
173
+ "\n",
174
+ " # Ensure the sentences are strings; convert or skip if not\n",
175
+ " sentence1 = str(row['sentence1']) if not pd.isna(row['sentence1']) else \"\"\n",
176
+ " sentence2 = str(row['sentence2']) if not pd.isna(row['sentence2']) else \"\"\n",
177
+ "\n",
178
+ " inputs = self.tokenizer(\n",
179
+ " sentence1, sentence2,\n",
180
+ " add_special_tokens=True,\n",
181
+ " max_length=self.max_length,\n",
182
+ " padding='max_length',\n",
183
+ " truncation=True,\n",
184
+ " return_tensors=\"pt\"\n",
185
+ " )\n",
186
+ "\n",
187
+ " label = torch.tensor(row['label'], dtype=torch.long)\n",
188
+ "\n",
189
+ " return {\n",
190
+ " 'input_ids': inputs['input_ids'].squeeze(0),\n",
191
+ " 'attention_mask': inputs['attention_mask'].squeeze(0),\n",
192
+ " 'label': label\n",
193
+ " }\n",
194
+ "\n",
195
+ "def collate_fn(batch):\n",
196
+ " input_ids = torch.stack([item['input_ids'] for item in batch])\n",
197
+ " attention_masks = torch.stack([item['attention_mask'] for item in batch])\n",
198
+ " labels = torch.stack([item['label'] for item in batch])\n",
199
+ "\n",
200
+ " return {\n",
201
+ " 'input_ids': input_ids,\n",
202
+ " 'attention_mask': attention_masks,\n",
203
+ " 'label': labels\n",
204
+ " }"
205
+ ]
206
+ },
207
+ {
208
+ "cell_type": "code",
209
+ "execution_count": 4,
210
+ "metadata": {},
211
+ "outputs": [
212
+ {
213
+ "data": {
214
+ "text/plain": [
215
+ "device(type='cuda')"
216
+ ]
217
+ },
218
+ "execution_count": 4,
219
+ "metadata": {},
220
+ "output_type": "execute_result"
221
+ }
222
+ ],
223
+ "source": [
224
+ "device"
225
+ ]
226
+ },
227
+ {
228
+ "cell_type": "code",
229
+ "execution_count": 5,
230
+ "metadata": {},
231
+ "outputs": [],
232
+ "source": [
233
+ "# Assuming you have a separate test set or validation set (e.g., df_test)\n",
234
+ "df_test = df[3_66_900:]\n",
235
+ "# Add padding token if not already\n",
236
+ "tokenizer.add_special_tokens({'pad_token': '[PAD]'})\n",
237
+ "\n",
238
+ "# Resize the model's token embeddings to fit the new tokenizer\n",
239
+ "model.resize_token_embeddings(len(tokenizer))\n",
240
+ "\n",
241
+ "# Create DataLoader for the test set\n",
242
+ "test_dataset = PlagiarismDataset(df_test, tokenizer)\n",
243
+ "test_data_loader = DataLoader(test_dataset, batch_size=16, shuffle=False, collate_fn=collate_fn)"
244
+ ]
245
+ },
246
+ {
247
+ "cell_type": "code",
248
+ "execution_count": 6,
249
+ "metadata": {},
250
+ "outputs": [
251
+ {
252
+ "name": "stdout",
253
+ "output_type": "stream",
254
+ "text": [
255
+ "Classification Report:\n",
256
+ " precision recall f1-score support\n",
257
+ "\n",
258
+ " 0 1.00 1.00 1.00 236\n",
259
+ " 1 1.00 1.00 1.00 237\n",
260
+ "\n",
261
+ " accuracy 1.00 473\n",
262
+ " macro avg 1.00 1.00 1.00 473\n",
263
+ "weighted avg 1.00 1.00 1.00 473\n",
264
+ "\n"
265
+ ]
266
+ }
267
+ ],
268
+ "source": [
269
+ "from sklearn.metrics import classification_report\n",
270
+ "# Function to evaluate model on the test set\n",
271
+ "# Set up device\n",
272
+ "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
273
+ "\n",
274
+ "# Move model to the appropriate device\n",
275
+ "model = model.to(device)\n",
276
+ "\n",
277
+ "# Function to evaluate the model\n",
278
+ "def evaluate_model(model, data_loader):\n",
279
+ " model.eval() # Set model to evaluation mode\n",
280
+ " preds_list = []\n",
281
+ " labels_list = []\n",
282
+ "\n",
283
+ " with torch.no_grad(): # Disable gradient calculation for evaluation\n",
284
+ " for batch in data_loader:\n",
285
+ " # Move input tensors to the same device as the model\n",
286
+ " input_ids = batch['input_ids'].to(device)\n",
287
+ " attention_mask = batch['attention_mask'].to(device)\n",
288
+ " labels = batch['label'].to(device)\n",
289
+ " \n",
290
+ " # Get model outputs\n",
291
+ " outputs = model(input_ids=input_ids, attention_mask=attention_mask)\n",
292
+ " preds = torch.argmax(outputs.logits, dim=1)\n",
293
+ "\n",
294
+ " # Append predictions and true labels to respective lists\n",
295
+ " preds_list.extend(preds.cpu().numpy())\n",
296
+ " labels_list.extend(labels.cpu().numpy())\n",
297
+ " \n",
298
+ " # Compute evaluation metrics\n",
299
+ " from sklearn.metrics import classification_report\n",
300
+ " report = classification_report(labels_list, preds_list)\n",
301
+ " print(\"Classification Report:\\n\", report)\n",
302
+ "\n",
303
+ "# Evaluate the model\n",
304
+ "evaluate_model(model, test_data_loader)"
305
+ ]
306
+ }
307
+ ],
308
+ "metadata": {
309
+ "kernelspec": {
310
+ "display_name": "LLM",
311
+ "language": "python",
312
+ "name": "python3"
313
+ },
314
+ "language_info": {
315
+ "codemirror_mode": {
316
+ "name": "ipython",
317
+ "version": 3
318
+ },
319
+ "file_extension": ".py",
320
+ "mimetype": "text/x-python",
321
+ "name": "python",
322
+ "nbconvert_exporter": "python",
323
+ "pygments_lexer": "ipython3",
324
+ "version": "3.9.20"
325
+ }
326
+ },
327
+ "nbformat": 4,
328
+ "nbformat_minor": 2
329
+ }