ssaroya commited on
Commit
765e3c5
·
1 Parent(s): 5596fcd

Upload 4 files

Browse files
Files changed (4) hide show
  1. utils/__init__.py +3 -0
  2. utils/datautils.py +189 -0
  3. utils/export.py +37 -0
  4. utils/modelutils.py +83 -0
utils/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .modelutils import DEV, find_layers, gen_conditions, torch_snr_error
2
+ from .datautils import set_seed, get_wikitext2, get_ptb, get_c4, get_ptb_new, get_c4_new, get_loaders
3
+ from .export import export_quant_table
utils/datautils.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+
4
+
5
+ def set_seed(seed):
6
+ np.random.seed(seed)
7
+ torch.random.manual_seed(seed)
8
+
9
+
10
+ def get_wikitext2(nsamples, seed, seqlen, model):
11
+ from datasets import load_dataset
12
+ traindata = load_dataset('wikitext', 'wikitext-2-raw-v1', split='train')
13
+ testdata = load_dataset('wikitext', 'wikitext-2-raw-v1', split='test')
14
+
15
+ from transformers import AutoTokenizer
16
+ try:
17
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=False)
18
+ except:
19
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=True)
20
+ trainenc = tokenizer("\n\n".join(traindata['text']), return_tensors='pt')
21
+ testenc = tokenizer("\n\n".join(testdata['text']), return_tensors='pt')
22
+
23
+ import random
24
+ random.seed(seed)
25
+ trainloader = []
26
+ for _ in range(nsamples):
27
+ i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
28
+ j = i + seqlen
29
+ inp = trainenc.input_ids[:, i:j]
30
+ tar = inp.clone()
31
+ tar[:, :-1] = -100
32
+ trainloader.append((inp, tar))
33
+ return trainloader, testenc
34
+
35
+
36
+ def get_ptb(nsamples, seed, seqlen, model):
37
+ from datasets import load_dataset
38
+ traindata = load_dataset('ptb_text_only', 'penn_treebank', split='train')
39
+ valdata = load_dataset('ptb_text_only', 'penn_treebank', split='validation')
40
+
41
+ from transformers import AutoTokenizer
42
+ try:
43
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=False)
44
+ except:
45
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=True)
46
+ trainenc = tokenizer("\n\n".join(traindata['sentence']), return_tensors='pt')
47
+ testenc = tokenizer("\n\n".join(valdata['sentence']), return_tensors='pt')
48
+
49
+ import random
50
+ random.seed(seed)
51
+ trainloader = []
52
+ for _ in range(nsamples):
53
+ i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
54
+ j = i + seqlen
55
+ inp = trainenc.input_ids[:, i:j]
56
+ tar = inp.clone()
57
+ tar[:, :-1] = -100
58
+ trainloader.append((inp, tar))
59
+ return trainloader, testenc
60
+
61
+
62
+ def get_c4(nsamples, seed, seqlen, model):
63
+ from datasets import load_dataset
64
+ traindata = load_dataset('allenai/c4', 'allenai--c4', data_files={'train': 'en/c4-train.00000-of-01024.json.gz'}, split='train', use_auth_token=False)
65
+ valdata = load_dataset('allenai/c4', 'allenai--c4', data_files={'validation': 'en/c4-validation.00000-of-00008.json.gz'}, split='validation', use_auth_token=False)
66
+
67
+ from transformers import AutoTokenizer
68
+ try:
69
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=False)
70
+ except:
71
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=True)
72
+
73
+ import random
74
+ random.seed(seed)
75
+ trainloader = []
76
+ for _ in range(nsamples):
77
+ while True:
78
+ i = random.randint(0, len(traindata) - 1)
79
+ trainenc = tokenizer(traindata[i]['text'], return_tensors='pt')
80
+ if trainenc.input_ids.shape[1] >= seqlen:
81
+ break
82
+ i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
83
+ j = i + seqlen
84
+ inp = trainenc.input_ids[:, i:j]
85
+ tar = inp.clone()
86
+ tar[:, :-1] = -100
87
+ trainloader.append((inp, tar))
88
+
89
+ import random
90
+ random.seed(0)
91
+ valenc = []
92
+ for _ in range(256):
93
+ while True:
94
+ i = random.randint(0, len(valdata) - 1)
95
+ tmp = tokenizer(valdata[i]['text'], return_tensors='pt')
96
+ if tmp.input_ids.shape[1] >= seqlen:
97
+ break
98
+ i = random.randint(0, tmp.input_ids.shape[1] - seqlen - 1)
99
+ j = i + seqlen
100
+ valenc.append(tmp.input_ids[:, i:j])
101
+ valenc = torch.hstack(valenc)
102
+
103
+ class TokenizerWrapper:
104
+
105
+ def __init__(self, input_ids):
106
+ self.input_ids = input_ids
107
+
108
+ valenc = TokenizerWrapper(valenc)
109
+
110
+ return trainloader, valenc
111
+
112
+
113
+ def get_ptb_new(nsamples, seed, seqlen, model):
114
+ from datasets import load_dataset
115
+ traindata = load_dataset('ptb_text_only', 'penn_treebank', split='train')
116
+ testdata = load_dataset('ptb_text_only', 'penn_treebank', split='test')
117
+
118
+ from transformers import AutoTokenizer
119
+ try:
120
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=False)
121
+ except:
122
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=True)
123
+ trainenc = tokenizer(" ".join(traindata['sentence']), return_tensors='pt')
124
+ testenc = tokenizer(" ".join(testdata['sentence']), return_tensors='pt')
125
+
126
+ import random
127
+ random.seed(seed)
128
+ trainloader = []
129
+ for _ in range(nsamples):
130
+ i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
131
+ j = i + seqlen
132
+ inp = trainenc.input_ids[:, i:j]
133
+ tar = inp.clone()
134
+ tar[:, :-1] = -100
135
+ trainloader.append((inp, tar))
136
+ return trainloader, testenc
137
+
138
+
139
+ def get_c4_new(nsamples, seed, seqlen, model):
140
+ from datasets import load_dataset
141
+ traindata = load_dataset('allenai/c4', 'allenai--c4', data_files={'train': 'en/c4-train.00000-of-01024.json.gz'}, split='train')
142
+ valdata = load_dataset('allenai/c4', 'allenai--c4', data_files={'validation': 'en/c4-validation.00000-of-00008.json.gz'}, split='validation')
143
+
144
+ from transformers import AutoTokenizer
145
+ try:
146
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=False)
147
+ except:
148
+ tokenizer = AutoTokenizer.from_pretrained(model, use_fast=True)
149
+
150
+ import random
151
+ random.seed(seed)
152
+ trainloader = []
153
+ for _ in range(nsamples):
154
+ while True:
155
+ i = random.randint(0, len(traindata) - 1)
156
+ trainenc = tokenizer(traindata[i]['text'], return_tensors='pt')
157
+ if trainenc.input_ids.shape[1] >= seqlen:
158
+ break
159
+ i = random.randint(0, trainenc.input_ids.shape[1] - seqlen - 1)
160
+ j = i + seqlen
161
+ inp = trainenc.input_ids[:, i:j]
162
+ tar = inp.clone()
163
+ tar[:, :-1] = -100
164
+ trainloader.append((inp, tar))
165
+
166
+ valenc = tokenizer(' '.join(valdata[:1100]['text']), return_tensors='pt')
167
+ valenc = valenc.input_ids[:, :(256 * seqlen)]
168
+
169
+ class TokenizerWrapper:
170
+
171
+ def __init__(self, input_ids):
172
+ self.input_ids = input_ids
173
+
174
+ valenc = TokenizerWrapper(valenc)
175
+
176
+ return trainloader, valenc
177
+
178
+
179
+ def get_loaders(name, nsamples=128, seed=0, seqlen=2048, model=''):
180
+ if 'wikitext2' in name:
181
+ return get_wikitext2(nsamples, seed, seqlen, model)
182
+ if 'ptb' in name:
183
+ if 'new' in name:
184
+ return get_ptb_new(nsamples, seed, seqlen, model)
185
+ return get_ptb(nsamples, seed, seqlen, model)
186
+ if 'c4' in name:
187
+ if 'new' in name:
188
+ return get_c4_new(nsamples, seed, seqlen, model)
189
+ return get_c4(nsamples, seed, seqlen, model)
utils/export.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import toml
3
+ import os
4
+
5
+
6
+ def export_quant_table(quantizers: dict, quant_dir: str, format: str = 'toml'):
7
+
8
+ table = {}
9
+
10
+ def save_tensor(name: str, tensor):
11
+ np.save(os.path.join(quant_dir, name), tensor.numpy())
12
+ return '{}.npy'.format(name)
13
+
14
+ for key, value in quantizers.items():
15
+ quantizer = value[0]
16
+
17
+ dump = dict()
18
+
19
+ sym = quantizer.sym
20
+ if not sym:
21
+ dump['zero'] = save_tensor(name=key + '.zero', tensor=value[2])
22
+ dump['scale'] = save_tensor(name=key + '.scale', tensor=value[1])
23
+ dump['wbits'] = value[4]
24
+ dump['groupsize'] = value[5]
25
+ if value[5] > 0:
26
+ dump['group_ids'] = save_tensor(name=key + '.group_ids', tensor=value[3])
27
+
28
+ dump['sym'] = sym
29
+ dump['perchannel'] = quantizer.perchannel
30
+
31
+ table[key] = dump
32
+
33
+ if not os.path.exists(quant_dir):
34
+ os.mkdir(quant_dir)
35
+
36
+ with open(os.path.join(quant_dir, 'quant.toml'), 'w') as f:
37
+ toml.dump(table, f)
utils/modelutils.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+
4
+ DEV = torch.device('cuda:0')
5
+
6
+
7
+ def find_layers(module, layers=[nn.Conv2d, nn.Linear], name=''):
8
+ if type(module) in layers:
9
+ return {name: module}
10
+ res = {}
11
+ for name1, child in module.named_children():
12
+ res.update(find_layers(child, layers=layers, name=name + '.' + name1 if name != '' else name1))
13
+ return res
14
+
15
+
16
+ def gen_conditions(_wbits, _groupsize):
17
+ wbits = _wbits
18
+ groupsize = _groupsize
19
+ conditions = []
20
+ while True:
21
+ if wbits >= 8:
22
+ if groupsize == -1 or groupsize == 32:
23
+ break
24
+
25
+ if groupsize > 32:
26
+ groupsize /= 2
27
+ else:
28
+ wbits *= 2
29
+ groupsize = _groupsize
30
+
31
+ conditions.append((int(wbits), int(groupsize)))
32
+ return conditions
33
+
34
+
35
+ # copy from https://github.com/openppl-public/ppq/blob/master/ppq/quantization/measure/norm.py
36
+ def torch_snr_error(y_pred: torch.Tensor, y_real: torch.Tensor, reduction: str = 'mean') -> torch.Tensor:
37
+ """
38
+ Compute SNR between y_pred(tensor) and y_real(tensor)
39
+
40
+ SNR can be calcualted as following equation:
41
+
42
+ SNR(pred, real) = (pred - real) ^ 2 / (real) ^ 2
43
+
44
+ if x and y are matrixs, SNR error over matrix should be the mean value of SNR error over all elements.
45
+
46
+ SNR(pred, real) = mean((pred - real) ^ 2 / (real) ^ 2)
47
+ Args:
48
+ y_pred (torch.Tensor): _description_
49
+ y_real (torch.Tensor): _description_
50
+ reduction (str, optional): _description_. Defaults to 'mean'.
51
+ Raises:
52
+ ValueError: _description_
53
+ ValueError: _description_
54
+ Returns:
55
+ torch.Tensor: _description_
56
+ """
57
+ y_pred = y_pred.type(torch.float32)
58
+ y_real = y_real.type(torch.float32)
59
+
60
+ if y_pred.shape != y_real.shape:
61
+ raise ValueError(f'Can not compute snr loss for tensors with different shape. '
62
+ f'({y_pred.shape} and {y_real.shape})')
63
+ reduction = str(reduction).lower()
64
+
65
+ if y_pred.ndim == 1:
66
+ y_pred = y_pred.unsqueeze(0)
67
+ y_real = y_real.unsqueeze(0)
68
+
69
+ y_pred = y_pred.flatten(start_dim=1)
70
+ y_real = y_real.flatten(start_dim=1)
71
+
72
+ noise_power = torch.pow(y_pred - y_real, 2).sum(dim=-1)
73
+ signal_power = torch.pow(y_real, 2).sum(dim=-1)
74
+ snr = (noise_power) / (signal_power + 1e-7)
75
+
76
+ if reduction == 'mean':
77
+ return torch.mean(snr)
78
+ elif reduction == 'sum':
79
+ return torch.sum(snr)
80
+ elif reduction == 'none':
81
+ return snr
82
+ else:
83
+ raise ValueError(f'Unsupported reduction method.')