KoichiYasuoka commited on
Commit
ac89c96
·
1 Parent(s): 3db3f34

initial release

Browse files
Files changed (9) hide show
  1. README.md +30 -0
  2. config.json +163 -0
  3. maker.py +89 -0
  4. merges.txt +0 -0
  5. pytorch_model.bin +3 -0
  6. special_tokens_map.json +37 -0
  7. tokenizer_config.json +22 -0
  8. upos.py +41 -0
  9. vocab.json +0 -0
README.md ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - "ja"
4
+ tags:
5
+ - "japanese"
6
+ - "token-classification"
7
+ - "pos"
8
+ base_model: ClassCat/gpt2-base-japanese-v2
9
+ datasets:
10
+ - "universal_dependencies"
11
+ license: "cc-by-sa-4.0"
12
+ pipeline_tag: "token-classification"
13
+ widget:
14
+ - text: "国境の長いトンネルを抜けると雪国であった。"
15
+ ---
16
+
17
+ # gpt2-base-japanese-upos
18
+
19
+ ## Model Description
20
+
21
+ This is a GPT-2 model for POS-tagging, derived from [gpt2-base-japanese-v2](https://huggingface.co/ClassCat/gpt2-base-japanese-v2). Every short-unit-word is tagged by [UPOS](https://universaldependencies.org/u/pos/) (Universal Part-Of-Speech) and [FEATS](https://universaldependencies.org/u/feat/).
22
+
23
+ ## How to Use
24
+
25
+ ```py
26
+ from transformers import pipeline
27
+ nlp=pipeline("upos","KoichiYasuoka/gpt2-base-japanese-upos",trust_remote_code=True,aggregation_strategy="simple")
28
+ print(nlp("国境の長いトンネルを抜けると雪国であった。"))
29
+ ```
30
+
config.json ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "activation_function": "gelu_new",
3
+ "architectures": [
4
+ "GPT2ForTokenClassification"
5
+ ],
6
+ "attn_pdrop": 0.1,
7
+ "bos_token_id": 0,
8
+ "custom_pipelines": {
9
+ "upos": {
10
+ "impl": "upos.BellmanFordTokenClassificationPipeline",
11
+ "pt": "AutoModelForTokenClassification"
12
+ }
13
+ },
14
+ "embd_pdrop": 0.1,
15
+ "eos_token_id": 0,
16
+ "id2label": {
17
+ "0": "ADJ",
18
+ "1": "B-ADJ",
19
+ "2": "I-ADJ",
20
+ "3": "ADJ|Polarity=Neg",
21
+ "4": "B-ADJ|Polarity=Neg",
22
+ "5": "I-ADJ|Polarity=Neg",
23
+ "6": "ADP",
24
+ "7": "B-ADP",
25
+ "8": "I-ADP",
26
+ "9": "ADV",
27
+ "10": "B-ADV",
28
+ "11": "I-ADV",
29
+ "12": "AUX",
30
+ "13": "B-AUX",
31
+ "14": "I-AUX",
32
+ "15": "AUX|Polarity=Neg",
33
+ "16": "B-AUX|Polarity=Neg",
34
+ "17": "I-AUX|Polarity=Neg",
35
+ "18": "CCONJ",
36
+ "19": "B-CCONJ",
37
+ "20": "I-CCONJ",
38
+ "21": "DET",
39
+ "22": "B-DET",
40
+ "23": "I-DET",
41
+ "24": "INTJ",
42
+ "25": "B-INTJ",
43
+ "26": "I-INTJ",
44
+ "27": "NOUN",
45
+ "28": "B-NOUN",
46
+ "29": "I-NOUN",
47
+ "30": "NOUN|Polarity=Neg",
48
+ "31": "B-NOUN|Polarity=Neg",
49
+ "32": "I-NOUN|Polarity=Neg",
50
+ "33": "NUM",
51
+ "34": "B-NUM",
52
+ "35": "I-NUM",
53
+ "36": "PART",
54
+ "37": "B-PART",
55
+ "38": "I-PART",
56
+ "39": "PRON",
57
+ "40": "B-PRON",
58
+ "41": "I-PRON",
59
+ "42": "PROPN",
60
+ "43": "B-PROPN",
61
+ "44": "I-PROPN",
62
+ "45": "PUNCT",
63
+ "46": "B-PUNCT",
64
+ "47": "I-PUNCT",
65
+ "48": "SCONJ",
66
+ "49": "B-SCONJ",
67
+ "50": "I-SCONJ",
68
+ "51": "SYM",
69
+ "52": "B-SYM",
70
+ "53": "I-SYM",
71
+ "54": "VERB",
72
+ "55": "B-VERB",
73
+ "56": "I-VERB",
74
+ "57": "X",
75
+ "58": "B-X",
76
+ "59": "I-X"
77
+ },
78
+ "initializer_range": 0.02,
79
+ "label2id": {
80
+ "ADJ": 0,
81
+ "ADJ|Polarity=Neg": 3,
82
+ "ADP": 6,
83
+ "ADV": 9,
84
+ "AUX": 12,
85
+ "AUX|Polarity=Neg": 15,
86
+ "B-ADJ": 1,
87
+ "B-ADJ|Polarity=Neg": 4,
88
+ "B-ADP": 7,
89
+ "B-ADV": 10,
90
+ "B-AUX": 13,
91
+ "B-AUX|Polarity=Neg": 16,
92
+ "B-CCONJ": 19,
93
+ "B-DET": 22,
94
+ "B-INTJ": 25,
95
+ "B-NOUN": 28,
96
+ "B-NOUN|Polarity=Neg": 31,
97
+ "B-NUM": 34,
98
+ "B-PART": 37,
99
+ "B-PRON": 40,
100
+ "B-PROPN": 43,
101
+ "B-PUNCT": 46,
102
+ "B-SCONJ": 49,
103
+ "B-SYM": 52,
104
+ "B-VERB": 55,
105
+ "B-X": 58,
106
+ "CCONJ": 18,
107
+ "DET": 21,
108
+ "I-ADJ": 2,
109
+ "I-ADJ|Polarity=Neg": 5,
110
+ "I-ADP": 8,
111
+ "I-ADV": 11,
112
+ "I-AUX": 14,
113
+ "I-AUX|Polarity=Neg": 17,
114
+ "I-CCONJ": 20,
115
+ "I-DET": 23,
116
+ "I-INTJ": 26,
117
+ "I-NOUN": 29,
118
+ "I-NOUN|Polarity=Neg": 32,
119
+ "I-NUM": 35,
120
+ "I-PART": 38,
121
+ "I-PRON": 41,
122
+ "I-PROPN": 44,
123
+ "I-PUNCT": 47,
124
+ "I-SCONJ": 50,
125
+ "I-SYM": 53,
126
+ "I-VERB": 56,
127
+ "I-X": 59,
128
+ "INTJ": 24,
129
+ "NOUN": 27,
130
+ "NOUN|Polarity=Neg": 30,
131
+ "NUM": 33,
132
+ "PART": 36,
133
+ "PRON": 39,
134
+ "PROPN": 42,
135
+ "PUNCT": 45,
136
+ "SCONJ": 48,
137
+ "SYM": 51,
138
+ "VERB": 54,
139
+ "X": 57
140
+ },
141
+ "layer_norm_epsilon": 1e-05,
142
+ "model_type": "gpt2",
143
+ "n_ctx": 1024,
144
+ "n_embd": 768,
145
+ "n_head": 12,
146
+ "n_inner": null,
147
+ "n_layer": 12,
148
+ "n_positions": 1024,
149
+ "reorder_and_upcast_attn": false,
150
+ "resid_pdrop": 0.1,
151
+ "scale_attn_by_inverse_layer_idx": false,
152
+ "scale_attn_weights": true,
153
+ "summary_activation": null,
154
+ "summary_first_dropout": 0.1,
155
+ "summary_proj_to_labels": true,
156
+ "summary_type": "cls_index",
157
+ "summary_use_proj": true,
158
+ "tokenizer_class": "GPT2Tokenizer",
159
+ "torch_dtype": "float32",
160
+ "transformers_version": "4.44.2",
161
+ "use_cache": true,
162
+ "vocab_size": 60000
163
+ }
maker.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #! /usr/bin/python3
2
+ src="ClassCat/gpt2-base-japanese-v2"
3
+ tgt="KoichiYasuoka/gpt2-base-japanese-upos"
4
+
5
+ import os
6
+ from transformers import AutoTokenizer,AutoConfig,GPT2ForTokenClassification,DataCollatorForTokenClassification,TrainingArguments,Trainer
7
+ os.system("test -f ja_gsd_modern.conllu || curl -LO https://github.com/KoichiYasuoka/SuPar-UniDic/raw/main/suparunidic/suparmodels/ja_gsd_modern.conllu")
8
+
9
+ class UPOSFileDataset(object):
10
+ def __init__(self,conllu,tokenizer):
11
+ self.conllu=open(conllu,"r",encoding="utf-8")
12
+ self.tokenizer=tokenizer
13
+ self.seeks=[0]
14
+ self.multiword={}
15
+ label=set(["SYM"])
16
+ s=self.conllu.readline()
17
+ while s!="":
18
+ if s=="\n":
19
+ self.seeks.append(self.conllu.tell())
20
+ else:
21
+ w=s.split("\t")
22
+ if len(w)==10:
23
+ if w[0].isdecimal():
24
+ label.add(w[3] if w[5]=="_" else w[3]+"|"+w[5])
25
+ elif w[0].find("-")>0:
26
+ t=w[0].split("-")
27
+ f,j,k=w[1],[],[]
28
+ for i in range(int(t[0]),int(t[1])+1):
29
+ w=self.conllu.readline().split("\t")
30
+ j.append(w[3] if w[5]=="_" else w[3]+"|"+w[5])
31
+ k.append(w[1])
32
+ p="+".join(j)
33
+ label.add(p)
34
+ if p in self.multiword:
35
+ self.multiword[p][f]=list(k)
36
+ else:
37
+ self.multiword[p]={f:list(k)}
38
+ s=self.conllu.readline()
39
+ lid={}
40
+ for i,l in enumerate(sorted(label)):
41
+ lid[l],lid["B-"+l],lid["I-"+l]=i*3,i*3+1,i*3+2
42
+ self.label2id=lid
43
+ def __call__(*args):
44
+ lid={l:i for i,l in enumerate(sorted(set(sum([list(t.label2id) for t in args],[]))))}
45
+ for t in args:
46
+ t.label2id=lid
47
+ return lid
48
+ def __del__(self):
49
+ self.conllu.close()
50
+ __len__=lambda self:len(self.seeks)-1
51
+ def __getitem__(self,i):
52
+ self.conllu.seek(self.seeks[i])
53
+ form,upos=[],[]
54
+ while self.conllu.tell()<self.seeks[i+1]:
55
+ w=self.conllu.readline().split("\t")
56
+ if len(w)==10:
57
+ form.append(w[1])
58
+ if w[0].isdecimal():
59
+ upos.append(w[3] if w[5]=="_" else w[3]+"|"+w[5])
60
+ elif w[0].find("-")>0:
61
+ t=w[0].split("-")
62
+ u=[]
63
+ for j in range(int(t[0]),int(t[1])+1):
64
+ k=self.conllu.readline().split("\t")
65
+ u.append(k[3] if k[5]=="_" else k[3]+"|"+k[5])
66
+ upos.append("+".join(u))
67
+ v=self.tokenizer(form,add_special_tokens=False)
68
+ i,u=[],[]
69
+ for j,(x,y) in enumerate(zip(v["input_ids"],upos)):
70
+ if x!=[]:
71
+ i+=x
72
+ u+=[y] if len(x)==1 else ["B-"+y]+["I-"+y]*(len(x)-1)
73
+ if len(i)<self.tokenizer.model_max_length-3:
74
+ ids=i
75
+ upos=u
76
+ else:
77
+ ids=i[0:self.tokenizer.model_max_length-2]
78
+ upos=u[0:self.tokenizer.model_max_length-2]
79
+ return {"input_ids":ids,"labels":[self.label2id[t] for t in upos]}
80
+
81
+ tkz=AutoTokenizer.from_pretrained(src,sep_token="<|endoftext|>",pad_token="<|endoftext|>",model_max_length=1024)
82
+ trainDS=UPOSFileDataset("ja_gsd_modern.conllu",tkz)
83
+ lid=trainDS.label2id
84
+ cfg=AutoConfig.from_pretrained(src,num_labels=len(lid),label2id=lid,id2label={i:l for l,i in lid.items()},ignore_mismatched_sizes=True)
85
+ arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=16,output_dir=tgt,overwrite_output_dir=True,save_total_limit=2,learning_rate=5e-05,warmup_ratio=0.1,save_safetensors=False)
86
+ trn=Trainer(args=arg,data_collator=DataCollatorForTokenClassification(tkz),model=GPT2ForTokenClassification.from_pretrained(src,config=cfg,ignore_mismatched_sizes=True),train_dataset=trainDS)
87
+ trn.train()
88
+ trn.save_model(tgt)
89
+ tkz.save_pretrained(tgt)
merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
pytorch_model.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:da6275b95a52373b507018ee815c727f9b788c85d4e87955043eaaab9b87c09a
3
+ size 527923170
special_tokens_map.json ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<|endoftext|>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "<|endoftext|>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "<|endoftext|>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "sep_token": {
24
+ "content": "<|endoftext|>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ },
30
+ "unk_token": {
31
+ "content": "<|endoftext|>",
32
+ "lstrip": false,
33
+ "normalized": false,
34
+ "rstrip": false,
35
+ "single_word": false
36
+ }
37
+ }
tokenizer_config.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ },
13
+ "bos_token": "<|endoftext|>",
14
+ "clean_up_tokenization_spaces": true,
15
+ "eos_token": "<|endoftext|>",
16
+ "keep_accents": true,
17
+ "model_max_length": 1024,
18
+ "pad_token": "<|endoftext|>",
19
+ "sep_token": "<|endoftext|>",
20
+ "tokenizer_class": "GPT2Tokenizer",
21
+ "unk_token": "<|endoftext|>"
22
+ }
upos.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import TokenClassificationPipeline
2
+
3
+ class BellmanFordTokenClassificationPipeline(TokenClassificationPipeline):
4
+ def __init__(self,**kwargs):
5
+ import numpy
6
+ super().__init__(**kwargs)
7
+ x=self.model.config.label2id
8
+ y=[k for k in x if not k.startswith("I-")]
9
+ self.transition=numpy.full((len(x),len(x)),numpy.nan)
10
+ for k,v in x.items():
11
+ for j in ["I-"+k[2:]] if k.startswith("B-") else [k]+y if k.startswith("I-") else y:
12
+ self.transition[v,x[j]]=0
13
+ def check_model_type(self,supported_models):
14
+ pass
15
+ def postprocess(self,model_outputs,**kwargs):
16
+ import numpy
17
+ if "logits" not in model_outputs:
18
+ return self.postprocess(model_outputs[0],**kwargs)
19
+ m=model_outputs["logits"][0].numpy()
20
+ e=numpy.exp(m-numpy.max(m,axis=-1,keepdims=True))
21
+ z=e/e.sum(axis=-1,keepdims=True)
22
+ for i in range(m.shape[0]-1,0,-1):
23
+ m[i-1]+=numpy.nanmax(m[i]+self.transition,axis=1)
24
+ k=[numpy.nanargmax(m[0]+self.transition[0])]
25
+ for i in range(1,m.shape[0]):
26
+ k.append(numpy.nanargmax(m[i]+self.transition[k[-1]]))
27
+ w=[{"entity":self.model.config.id2label[j],"start":s,"end":e,"score":z[i,j]} for i,((s,e),j) in enumerate(zip(model_outputs["offset_mapping"][0].tolist(),k)) if s<e]
28
+ if "aggregation_strategy" in kwargs and kwargs["aggregation_strategy"]!="none":
29
+ for i,t in reversed(list(enumerate(w))):
30
+ p=t.pop("entity")
31
+ if p.startswith("I-"):
32
+ w[i-1]["score"]=min(w[i-1]["score"],t["score"])
33
+ w[i-1]["end"]=w.pop(i)["end"]
34
+ elif p.startswith("B-"):
35
+ t["entity_group"]=p[2:]
36
+ else:
37
+ t["entity_group"]=p
38
+ for t in w:
39
+ t["text"]=model_outputs["sentence"][t["start"]:t["end"]]
40
+ return w
41
+
vocab.json ADDED
The diff for this file is too large to render. See raw diff