star092304 commited on
Commit
d4ed231
·
verified ·
1 Parent(s): 1a5251f

Upload 8 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ training_curves.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: en
3
+ tags:
4
+ - ielts
5
+ - automated-essay-scoring
6
+ - deberta-v3
7
+ - regression
8
+ - nlp
9
+ library_name: transformers
10
+ license: mit
11
+ metrics:
12
+ - qwk
13
+ - rmse
14
+ pipeline_tag: text-classification
15
+ ---
aes_meta.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "PromptAwareIELTSScorer",
3
+ "backbone": "microsoft/deberta-v3-base",
4
+ "trait_cols": [
5
+ "TA",
6
+ "CC",
7
+ "LR",
8
+ "GRA"
9
+ ],
10
+ "score_min": 0.0,
11
+ "score_max": 9.0,
12
+ "max_len": 512,
13
+ "head_hidden": 256,
14
+ "head_dropout": 0.3,
15
+ "msd_k": 5,
16
+ "pool_dropout": 0.1,
17
+ "prompt_col": "prompt",
18
+ "essay_col": "essay",
19
+ "best_val_qwk": 0.6583,
20
+ "best_epoch": 4,
21
+ "final_metrics": {
22
+ "TA": 0.6032,
23
+ "CC": 0.5727,
24
+ "LR": 0.7023,
25
+ "GRA": 0.7462,
26
+ "OverallBand": 0.6671,
27
+ "avg_qwk": 0.6583,
28
+ "val_loss": 0.02651
29
+ }
30
+ }
config.json ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "PromptAwareIELTSScorer"
4
+ ],
5
+ "attention_probs_dropout_prob": 0.1,
6
+ "bos_token_id": null,
7
+ "dtype": "float32",
8
+ "eos_token_id": null,
9
+ "hidden_act": "gelu",
10
+ "hidden_dropout_prob": 0.1,
11
+ "hidden_size": 768,
12
+ "initializer_range": 0.02,
13
+ "intermediate_size": 3072,
14
+ "layer_norm_eps": 1e-07,
15
+ "legacy": true,
16
+ "max_position_embeddings": 512,
17
+ "max_relative_positions": -1,
18
+ "model_type": "deberta-v2",
19
+ "norm_rel_ebd": "layer_norm",
20
+ "num_attention_heads": 12,
21
+ "num_hidden_layers": 12,
22
+ "pad_token_id": 0,
23
+ "pooler_dropout": 0,
24
+ "pooler_hidden_act": "gelu",
25
+ "pooler_hidden_size": 768,
26
+ "pos_att_type": [
27
+ "p2c",
28
+ "c2p"
29
+ ],
30
+ "position_biased_input": false,
31
+ "position_buckets": 256,
32
+ "relative_attention": true,
33
+ "sep_token_id": 2,
34
+ "share_att_key": true,
35
+ "tie_word_embeddings": true,
36
+ "transformers_version": "5.0.0",
37
+ "type_vocab_size": 0,
38
+ "vocab_size": 128100
39
+ }
modeling_ielts.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+ import numpy as np
6
+ from transformers import DebertaV2Model, DebertaV2PreTrainedModel, DebertaV2Config
7
+
8
+ TRAIT_COLS = ["TA", "CC", "LR", "GRA"]
9
+ SCORE_MIN = 0.0
10
+ SCORE_MAX = 9.0
11
+ HEAD_HIDDEN = 256
12
+ HEAD_DROPOUT = 0.3
13
+ MSD_K = 5
14
+ POOL_DROPOUT = 0.1
15
+
16
+ BAND_GROUP_RULES = [
17
+ (-float("inf"), 4.0, 3.5),
18
+ (4.0, 5.5, 4.5),
19
+ (5.5, 6.0, 5.5),
20
+ (6.0, 6.5, 6.0),
21
+ (6.5, 7.0, 6.5),
22
+ (7.0, 7.5, 7.0),
23
+ (7.5, 8.0, 7.5),
24
+ (8.0, float("inf"), 8.5),
25
+ ]
26
+
27
+ def map_score_to_continuous(raw_score: float) -> float:
28
+ for lo, hi, cont in BAND_GROUP_RULES:
29
+ if lo <= raw_score < hi:
30
+ return cont
31
+ return BAND_GROUP_RULES[-1][2]
32
+
33
+ class AttentionPooling(nn.Module):
34
+ def __init__(self, hidden_size: int, dropout: float = POOL_DROPOUT):
35
+ super().__init__()
36
+ self.attention = nn.Linear(hidden_size, 1)
37
+ self.dropout = nn.Dropout(dropout)
38
+
39
+ def forward(self, hidden_states, pool_mask):
40
+ hidden_states = self.dropout(hidden_states)
41
+ scores = self.attention(hidden_states).squeeze(-1)
42
+ scores = scores.masked_fill(pool_mask == 0, -1e4)
43
+ weights = torch.softmax(scores, dim=-1)
44
+ pooled = torch.bmm(weights.unsqueeze(1), hidden_states)
45
+ return pooled.squeeze(1)
46
+
47
+ class TraitHead(nn.Module):
48
+ def __init__(self, hidden_size, mid_size=HEAD_HIDDEN, dropout=HEAD_DROPOUT):
49
+ super().__init__()
50
+ self.net = nn.Sequential(
51
+ nn.Linear(hidden_size, mid_size),
52
+ nn.GELU(),
53
+ nn.Dropout(dropout),
54
+ nn.Linear(mid_size, 1),
55
+ nn.Sigmoid(),
56
+ )
57
+
58
+ def forward(self, x):
59
+ return self.net(x).squeeze(-1)
60
+
61
+ class PromptAwareIELTSScorer(DebertaV2PreTrainedModel):
62
+ config_class = DebertaV2Config
63
+
64
+ def __init__(self, config):
65
+ super().__init__(config)
66
+ self.deberta = DebertaV2Model(config)
67
+ H = config.hidden_size
68
+
69
+ self.attention_pooling = AttentionPooling(H)
70
+ self.shared_proj = nn.Sequential(
71
+ nn.Linear(H, H),
72
+ nn.GELU(),
73
+ )
74
+ self.msd_dropouts = nn.ModuleList([nn.Dropout(HEAD_DROPOUT) for _ in range(MSD_K)])
75
+
76
+ self.head_ta = TraitHead(H)
77
+ self.head_cc = TraitHead(H)
78
+ self.head_lr = TraitHead(H)
79
+ self.head_gra = TraitHead(H)
80
+ self.post_init()
81
+
82
+ def get_backbone_params(self):
83
+ return list(self.deberta.parameters())
84
+
85
+ def get_head_params(self):
86
+ return (list(self.attention_pooling.parameters()) +
87
+ list(self.shared_proj.parameters()) +
88
+ list(self.head_ta.parameters()) +
89
+ list(self.head_cc.parameters()) +
90
+ list(self.head_lr.parameters()) +
91
+ list(self.head_gra.parameters()))
92
+
93
+ def _essay_only_mask(self, input_ids, attention_mask):
94
+ sep_token_id = getattr(self.config, 'sep_token_id', None)
95
+ if sep_token_id is None:
96
+ sep_token_id = 2
97
+
98
+ essay_mask = attention_mask.clone()
99
+ is_sep = (input_ids == sep_token_id)
100
+ has_sep = is_sep.any(dim=1)
101
+
102
+ sep_cumsum = is_sep.cumsum(dim=1)
103
+ before_first_sep = (sep_cumsum == 0)
104
+ at_first_sep = is_sep & (sep_cumsum == 1)
105
+ prompt_region = (before_first_sep | at_first_sep) & has_sep.unsqueeze(1)
106
+
107
+ essay_mask = essay_mask.masked_fill(prompt_region, 0)
108
+
109
+ all_zero = (essay_mask.sum(dim=1) == 0)
110
+ if all_zero.any():
111
+ essay_mask = essay_mask.clone()
112
+ essay_mask[all_zero] = attention_mask[all_zero]
113
+
114
+ return essay_mask
115
+
116
+ def encode(self, input_ids, attention_mask):
117
+ out = self.deberta(input_ids=input_ids, attention_mask=attention_mask,
118
+ output_hidden_states=False)
119
+ last_hidden = out.last_hidden_state
120
+ essay_mask = self._essay_only_mask(input_ids, attention_mask)
121
+ context = self.attention_pooling(last_hidden, essay_mask)
122
+ shared = self.shared_proj(context)
123
+ return shared
124
+
125
+ def forward(self, input_ids=None, attention_mask=None, labels=None, **kwargs):
126
+ shared = self.encode(input_ids, attention_mask)
127
+
128
+ logits_sum = None
129
+ for dropout in self.msd_dropouts:
130
+ h = dropout(shared)
131
+ logits_k = torch.stack([
132
+ self.head_ta(h),
133
+ self.head_cc(h),
134
+ self.head_lr(h),
135
+ self.head_gra(h),
136
+ ], dim=1)
137
+ logits_sum = logits_k if logits_sum is None else logits_sum + logits_k
138
+
139
+ logits = logits_sum / len(self.msd_dropouts)
140
+
141
+ loss = None
142
+ if labels is not None:
143
+ loss = F.smooth_l1_loss(logits, labels, beta=0.3)
144
+ return {"loss": loss, "logits": logits}
145
+
146
+ def predict_essay(model, tokenizer, prompt: str, essay: str,
147
+ max_length: int = 512, device: str = "cpu") -> dict:
148
+ model.eval()
149
+ enc = tokenizer(prompt, essay, return_tensors="pt",
150
+ truncation=True, max_length=max_length, padding=False)
151
+ enc = {k: v.to(device) for k, v in enc.items() if k in ['input_ids', 'attention_mask']}
152
+ with torch.no_grad():
153
+ out = model(**enc)
154
+
155
+ preds_9 = out["logits"][0].cpu().numpy() * (SCORE_MAX - SCORE_MIN) + SCORE_MIN
156
+ ta, cc, lr, gra = preds_9
157
+
158
+ overall = round(float((ta + cc + lr + gra) / 4.0) * 2) / 2.0
159
+
160
+ return {
161
+ "TA": round(float(ta), 2),
162
+ "CC": round(float(cc), 2),
163
+ "LR": round(float(lr), 2),
164
+ "GRA": round(float(gra), 2),
165
+ "OverallBand": overall,
166
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": true,
3
+ "backend": "tokenizers",
4
+ "bos_token": "[CLS]",
5
+ "cls_token": "[CLS]",
6
+ "do_lower_case": false,
7
+ "eos_token": "[SEP]",
8
+ "extra_special_tokens": [
9
+ "[PAD]",
10
+ "[CLS]",
11
+ "[SEP]"
12
+ ],
13
+ "is_local": false,
14
+ "mask_token": "[MASK]",
15
+ "model_max_length": 1000000000000000019884624838656,
16
+ "pad_token": "[PAD]",
17
+ "sep_token": "[SEP]",
18
+ "split_by_punct": false,
19
+ "tokenizer_class": "DebertaV2Tokenizer",
20
+ "unk_id": 3,
21
+ "unk_token": "[UNK]",
22
+ "vocab_type": "spm"
23
+ }
training_curves.png ADDED

Git LFS Details

  • SHA256: c90b97d53c6337c741416408a898ce9ea136eb6cae49a649230227b883f23083
  • Pointer size: 131 Bytes
  • Size of remote file: 527 kB
training_history.csv ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ epoch,train_loss,TA,CC,LR,GRA,OverallBand,avg_qwk,val_loss
2
+ 1,0.042457533743399514,0.3564,0.338,0.5395,0.6175,0.4654,0.4634,0.03586
3
+ 2,0.026793291574542383,0.5092,0.4707,0.6512,0.7061,0.6022,0.5879,0.0284
4
+ 3,0.02471122434183812,0.5824,0.5452,0.7001,0.7378,0.6509,0.6433,0.02702
5
+ 4,0.022730398019798117,0.6032,0.5727,0.7023,0.7462,0.6671,0.6583,0.02651
6
+ 5,0.02116386474276467,0.525,0.4968,0.6399,0.6876,0.5933,0.5885,0.03349
7
+ 6,0.019647491585986734,0.5396,0.5142,0.6452,0.6987,0.6057,0.6007,0.03209