Views
No views yet
CodeBERTa-small-v1 checkpoint on the task of classifying a sample of code into the programming language it's written in (programming language identification).1CODEBERTA_LANGUAGE_ID = "huggingface/CodeBERTa-language-id"
2
3tokenizer = RobertaTokenizer.from_pretrained(CODEBERTA_LANGUAGE_ID)
4model = RobertaForSequenceClassification.from_pretrained(CODEBERTA_LANGUAGE_ID)
5
6input_ids = tokenizer.encode(CODE_TO_IDENTIFY)
7logits = model(input_ids)[0]
8
9language_idx = logits.argmax() # index for the resulting label1from transformers import TextClassificationPipeline
2
3pipeline = TextClassificationPipeline(
4 model=RobertaForSequenceClassification.from_pretrained(CODEBERTA_LANGUAGE_ID),
5 tokenizer=RobertaTokenizer.from_pretrained(CODEBERTA_LANGUAGE_ID)
6)
7
8pipeline(CODE_TO_IDENTIFY)1pipeline("""
2def f(x):
3 return x**2
4""")
5# [{'label': 'python', 'score': 0.9999965}]1pipeline("const foo = 'bar'")
2# [{'label': 'javascript', 'score': 0.9977546}]const token from the assignment?1pipeline("foo = 'bar'")
2# [{'label': 'javascript', 'score': 0.7176245}]1pipeline("foo = u'bar'")
2# [{'label': 'python', 'score': 0.7638422}]u string modifier).1pipeline("echo $FOO")
2# [{'label': 'php', 'score': 0.9995257}]1pipeline("outcome := rand.Intn(6) + 1")
2# [{'label': 'go', 'score': 0.9936151}]:= (the assignment operator in Go) are perfect predictors of the underlying language:1pipeline(":=")
2# [{'label': 'go', 'score': 0.9998052}]:= are represented by a single token:1self.tokenizer.encode(" :=", add_special_tokens=False)
2# [521]1import gzip
2import json
3import logging
4import os
5from pathlib import Path
6from typing import Dict, List, Tuple
7
8import numpy as np
9import torch
10from sklearn.metrics import f1_score
11from tokenizers.implementations.byte_level_bpe import ByteLevelBPETokenizer
12from tokenizers.processors import BertProcessing
13from torch.nn.utils.rnn import pad_sequence
14from torch.utils.data import DataLoader, Dataset
15from torch.utils.data.dataset import Dataset
16from torch.utils.tensorboard.writer import SummaryWriter
17from tqdm import tqdm, trange
18
19from transformers import RobertaForSequenceClassification
20from transformers.data.metrics import acc_and_f1, simple_accuracy
21
22
23logging.basicConfig(level=logging.INFO)
24
25
26CODEBERTA_PRETRAINED = "huggingface/CodeBERTa-small-v1"
27
28LANGUAGES = [
29 "go",
30 "java",
31 "javascript",
32 "php",
33 "python",
34 "ruby",
35]
36FILES_PER_LANGUAGE = 1
37EVALUATE = True
38
39# Set up tokenizer
40tokenizer = ByteLevelBPETokenizer("./pretrained/vocab.json", "./pretrained/merges.txt",)
41tokenizer._tokenizer.post_processor = BertProcessing(
42 ("</s>", tokenizer.token_to_id("</s>")), ("<s>", tokenizer.token_to_id("<s>")),
43)
44tokenizer.enable_truncation(max_length=512)
45
46# Set up Tensorboard
47tb_writer = SummaryWriter()
48
49
50class CodeSearchNetDataset(Dataset):
51 examples: List[Tuple[List[int], int]]
52
53 def __init__(self, split: str = "train"):
54 """
55 train | valid | test
56 """
57
58 self.examples = []
59
60 src_files = []
61 for language in LANGUAGES:
62 src_files += list(
63 Path("../CodeSearchNet/resources/data/").glob(f"{language}/final/jsonl/{split}/*.jsonl.gz")
64 )[:FILES_PER_LANGUAGE]
65 for src_file in src_files:
66 label = src_file.parents[3].name
67 label_idx = LANGUAGES.index(label)
68 print("🔥", src_file, label)
69 lines = []
70 fh = gzip.open(src_file, mode="rt", encoding="utf-8")
71 for line in fh:
72 o = json.loads(line)
73 lines.append(o["code"])
74 examples = [(x.ids, label_idx) for x in tokenizer.encode_batch(lines)]
75 self.examples += examples
76 print("🔥🔥")
77
78 def __len__(self):
79 return len(self.examples)
80
81 def __getitem__(self, i):
82 # We’ll pad at the batch level.
83 return self.examples[i]
84
85
86model = RobertaForSequenceClassification.from_pretrained(CODEBERTA_PRETRAINED, num_labels=len(LANGUAGES))
87
88train_dataset = CodeSearchNetDataset(split="train")
89eval_dataset = CodeSearchNetDataset(split="test")
90
91
92def collate(examples):
93 input_ids = pad_sequence([torch.tensor(x[0]) for x in examples], batch_first=True, padding_value=1)
94 labels = torch.tensor([x[1] for x in examples])
95 # ^^ uncessary .unsqueeze(-1)
96 return input_ids, labels
97
98
99train_dataloader = DataLoader(train_dataset, batch_size=256, shuffle=True, collate_fn=collate)
100
101batch = next(iter(train_dataloader))
102
103
104model.to("cuda")
105model.train()
106for param in model.roberta.parameters():
107 param.requires_grad = False
108## ^^ Only train final layer.
109
110print(f"num params:", model.num_parameters())
111print(f"num trainable params:", model.num_parameters(only_trainable=True))
112
113
114def evaluate():
115 eval_loss = 0.0
116 nb_eval_steps = 0
117 preds = np.empty((0), dtype=np.int64)
118 out_label_ids = np.empty((0), dtype=np.int64)
119
120 model.eval()
121
122 eval_dataloader = DataLoader(eval_dataset, batch_size=512, collate_fn=collate)
123 for step, (input_ids, labels) in enumerate(tqdm(eval_dataloader, desc="Eval")):
124 with torch.no_grad():
125 outputs = model(input_ids=input_ids.to("cuda"), labels=labels.to("cuda"))
126 loss = outputs[0]
127 logits = outputs[1]
128 eval_loss += loss.mean().item()
129 nb_eval_steps += 1
130 preds = np.append(preds, logits.argmax(dim=1).detach().cpu().numpy(), axis=0)
131 out_label_ids = np.append(out_label_ids, labels.detach().cpu().numpy(), axis=0)
132 eval_loss = eval_loss / nb_eval_steps
133 acc = simple_accuracy(preds, out_label_ids)
134 f1 = f1_score(y_true=out_label_ids, y_pred=preds, average="macro")
135 print("=== Eval: loss ===", eval_loss)
136 print("=== Eval: acc. ===", acc)
137 print("=== Eval: f1 ===", f1)
138 # print(acc_and_f1(preds, out_label_ids))
139 tb_writer.add_scalars("eval", {"loss": eval_loss, "acc": acc, "f1": f1}, global_step)
140
141
142### Training loop
143
144global_step = 0
145train_iterator = trange(0, 4, desc="Epoch")
146optimizer = torch.optim.AdamW(model.parameters())
147for _ in train_iterator:
148 epoch_iterator = tqdm(train_dataloader, desc="Iteration")
149 for step, (input_ids, labels) in enumerate(epoch_iterator):
150 optimizer.zero_grad()
151 outputs = model(input_ids=input_ids.to("cuda"), labels=labels.to("cuda"))
152 loss = outputs[0]
153 loss.backward()
154 tb_writer.add_scalar("training_loss", loss.item(), global_step)
155 optimizer.step()
156 global_step += 1
157 if EVALUATE and global_step % 50 == 0:
158 evaluate()
159 model.train()
160
161
162evaluate()
163
164os.makedirs("./models/CodeBERT-language-id", exist_ok=True)
165model.save_pretrained("./models/CodeBERT-language-id")1@article{husain_codesearchnet_2019,
2 title = {{CodeSearchNet} {Challenge}: {Evaluating} the {State} of {Semantic} {Code} {Search}},
3 shorttitle = {{CodeSearchNet} {Challenge}},
4 url = {http://arxiv.org/abs/1909.09436},
5 urldate = {2020-03-12},
6 journal = {arXiv:1909.09436 [cs, stat]},
7 author = {Husain, Hamel and Wu, Ho-Hsiang and Gazit, Tiferet and Allamanis, Miltiadis and Brockschmidt, Marc},
8 month = sep,
9 year = {2019},
10 note = {arXiv: 1909.09436},
11}