camilaaeromoca commited on
Commit
13defca
·
verified ·
1 Parent(s): 40da916

Delete modelo.py

Browse files
Files changed (1) hide show
  1. modelo.py +0 -283
modelo.py DELETED
@@ -1,283 +0,0 @@
1
- python -m pip install --upgrade pip
2
-
3
-
4
- pip install watermark
5
- pip install transformers==4.31.0
6
- pip install gradio
7
- pip install torch==2.0.1
8
- pip install accelerate
9
- # Imports
10
- import torch
11
- import transformers
12
- import numpy as np
13
- import torch.nn.functional as F
14
- from accelerate import Accelerator
15
- from torch.utils.data import Dataset
16
- from transformers import AutoConfig, AutoModelForCausalLM, GPT2Tokenizer
17
- from transformers import GPT2Tokenizer
18
-
19
-
20
- # Versão da Linguagem Python
21
- from platform import python_version
22
- print('Versão da Linguagem Python Usada Neste Jupyter Notebook:', python_version())
23
-
24
- # Tamanho do vocabulário
25
- vocab_size = 13
26
- # Comprimento da sequência
27
- sequence_length = 4
28
- # Comprimento do resultado
29
- result_length = 2
30
- # Comprimento do contexto
31
- context_length = sequence_length + result_length
32
- # Parâmetros de configuração do modelo GPT-2
33
- config = AutoConfig.from_pretrained("gpt2",
34
- vocab_size = vocab_size,
35
- n_ctx = context_length,
36
- n_head = 4,
37
- n_layer = 2)
38
-
39
- # Carrega o modelo
40
- modelo = AutoModelForCausalLM.from_config(config)
41
- # Função para calcular o tamanho do modelo
42
- def model_size(model):
43
- return sum(t.numel() for t in modelo.parameters())
44
- print(f'Tamanho do Modelo: {model_size(modelo)/1000**2:.1f}M parâmetros')
45
- #Tamanho do Modelo: 15.0M parâmetros
46
- #Este modelo tem 15 milhões de parâmetros em vez dos 111 milhões de parâmetros da configuração padrão "gpt2".
47
-
48
- type(modelo)
49
- transformers.models.gpt2.modeling_gpt2.GPT2LMHeadModel
50
- # Salva o modelo em disco
51
- modelo.save_pretrained("modelos/modelo_inicial")
52
-
53
- # Definindo uma classe chamada NumberTokenizer, que é usada para tokenizar os números
54
- class DSATokenizer:
55
-
56
- # Método construtor da classe, que é executado quando um objeto dessa classe é criado
57
- def __init__(self, numbers_qty = 10):
58
-
59
- # Lista de tokens possíveis que o tokenizador pode encontrar
60
- vocab = ['+', '=', '-1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
61
-
62
- # Definindo a quantidade de números que o tokenizador pode lidar
63
- self.numbers_qty = numbers_qty
64
-
65
- # Definindo o token de preenchimento (padding)
66
- self.pad_token = '-1'
67
-
68
- # Criando um dicionário que mapeia cada token para um índice único
69
- self.encoder = {str(v):i for i,v in enumerate(vocab)}
70
-
71
- # Criando um dicionário que mapeia cada índice único de volta ao token correspondente
72
- self.decoder = {i:str(v) for i,v in enumerate(vocab)}
73
-
74
- # Obtendo o índice do token de preenchimento no encoder
75
- self.pad_token_id = self.encoder[self.pad_token]
76
-
77
- # Método para decodificar uma lista de IDs de token de volta para uma string
78
- def decode(self, token_ids):
79
- return ' '.join(self.decoder[t] for t in token_ids)
80
-
81
- # Método que é chamado quando o objeto da classe é invocado como uma função
82
- def __call__(self, text):
83
- # Dividindo o texto em tokens individuais e retornando uma lista dos IDs correspondentes
84
- return [self.encoder[t] for t in text.split()]
85
-
86
-
87
- # Cria o objeto do tokenizador
88
- tokenizer = DSATokenizer(vocab_size)
89
- # Decoder do tokenizador
90
- tokenizer.decoder
91
-
92
- # Testando o tokenizador
93
- tokenizer("1 + 1 = 2")
94
-
95
- # Definindo uma classe chamada CriaDataset, que herda da classe Dataset do PyTorch
96
- class CriaDataset(Dataset):
97
-
98
- # Método construtor da classe, que é executado quando um objeto dessa classe é criado
99
- def __init__(self, split, length = 6):
100
-
101
- # Verificando se a divisão do dataset (split) é 'treino' ou 'teste'
102
- assert split in {'treino', 'teste'}
103
- self.split = split
104
- self.length = length
105
-
106
- # Definindo o método len que retorna o tamanho do dataset.
107
- # Nesse caso, o tamanho é fixo e igual a 1 milhão.
108
- def __len__(self):
109
- return 1000000
110
-
111
- # Definindo o método getitem que é usado para obter um item específico do dataset
112
- def __getitem__(self, idx):
113
-
114
- # Criando uma lista com todos os números disponíveis que não são tokens de padding e são numéricos
115
- available_numbers = [int(n) for n in tokenizer.decoder.values() if n != tokenizer.pad_token and str(n).isnumeric()]
116
-
117
- # Selecionando aleatoriamente números da lista de números disponíveis para criar uma entrada (input)
118
- inp = torch.tensor(np.random.choice(available_numbers, size = result_length))
119
-
120
- # Calculando a soma dos números selecionados e criando um tensor
121
- sol = torch.tensor([int(i) for i in str(inp.sum().item())])
122
-
123
- # Preenchendo o tensor com zeros para que tenha o tamanho desejado
124
- sol = torch.nn.functional.pad(sol, (1 if sol.size()[0] == 1 else 0,0), 'constant', 0)
125
-
126
- # Concatenando a entrada e a solução em um tensor
127
- cat = torch.cat((inp, sol), dim = 0)
128
-
129
- # Criando os tensores de entrada e alvo para o treinamento do modelo
130
- x = cat[:-1].clone()
131
- y = cat[1:].clone()
132
-
133
- # Definindo o primeiro elemento do tensor alvo como o token de padding
134
- y[:1] = int(tokenizer.pad_token)
135
-
136
- # Transformando os tensores x e y em strings
137
- x = str(x[0].item()) + ' + ' + str(x[1].item()) + ' = ' + str(x[2].item())
138
- y = '-1 ' + str(y[0].item()) + ' -1 ' + str(y[1].item()) + ' ' + str(y[2].item())
139
-
140
- # Tokenizando as strings de entrada e alvo
141
- tokenized_input = tokenizer(x)
142
- tokenized_output = tokenizer(y)
143
-
144
- # Retornando os tensores de entrada e alvo como itens do dataset
145
- return torch.tensor(tokenized_input), torch.tensor(tokenized_output)
146
-
147
- dataset_treino = CriaDataset('treino', length = sequence_length)
148
- dataset_teste = CriaDataset('teste', length = sequence_length)
149
- x, y = dataset_treino[0]
150
- x
151
-
152
- y
153
-
154
- print(tokenizer.decode(x.numpy()))
155
- print(tokenizer.decode(y.numpy()))
156
-
157
- num_epochs = 2
158
- batch_size = 100
159
- optimizer = torch.optim.Adam(modelo.parameters())
160
- dados = torch.utils.data.DataLoader(dataset_treino, shuffle = True, batch_size = batch_size)
161
-
162
- import accelerate
163
- from accelerate import Accelerator
164
- accelerator = Accelerator()
165
-
166
- modelo, optimizer, dados = accelerator.prepare(modelo, optimizer, dados)
167
-
168
- modelo.train()
169
-
170
-
171
- # Iniciando o loop para as épocas de treinamento
172
- for epoch in range(num_epochs):
173
-
174
- # Iterando por cada batch (conjunto) de dados de entrada e alvos no dataset de treinamento
175
- for source, targets in dados:
176
-
177
- # Resetando os gradientes acumulados no otimizador
178
- optimizer.zero_grad()
179
-
180
- # Calculando a perda (loss) através da entropia cruzada entre as previsões do modelo e os alvos verdadeiros.
181
- # Os tensores são "achatados" para que possam ser passados para a função de entropia cruzada.
182
- # O índice do token de preenchimento (pad_token) é ignorado no cálculo da perda.
183
- loss = F.cross_entropy(modelo(source).logits.flatten(end_dim = 1),
184
- targets.flatten(end_dim = 1),
185
- ignore_index = tokenizer.pad_token_id)
186
-
187
- # Calculando os gradientes da perda em relação aos parâmetros do modelo
188
- accelerator.backward(loss)
189
-
190
- # Atualizando os parâmetros do modelo utilizando os gradientes calculados
191
- optimizer.step()
192
-
193
- # Recalculando a perda após a etapa de otimização.
194
- loss = F.cross_entropy(modelo(source).logits.flatten(end_dim = 1),
195
- targets.flatten(end_dim = 1),
196
- ignore_index = tokenizer.pad_token_id)
197
-
198
- # Imprimindo a época atual e a perda após cada época de treinamento
199
- print(f'Epoch: {epoch+1}/{num_epochs} --- Erro: {loss.item()}')
200
-
201
- # Definindo a função gera_solution com três parâmetros: input, solution_length e model
202
- def faz_previsao(entrada, solution_length = 6, model = modelo):
203
-
204
- # Colocando o modelo em modo de avaliação.
205
- model.eval()
206
-
207
- # Convertendo a entrada (string) em tensor utilizando o tokenizer.
208
- # O tensor é uma estrutura de dados que o modelo de aprendizado de máquina pode processar.
209
- entrada = torch.tensor(tokenizer(entrada))
210
-
211
- # Enviando o tensor de entrada para o dispositivo de cálculo disponível (CPU ou GPU)
212
- entrada = entrada.to(accelerator.device)
213
-
214
- # Iniciando uma lista vazia para armazenar a solução
215
- solution = []
216
-
217
- # Loop que gera a solução de comprimento solution_length
218
- for i in range(solution_length):
219
-
220
- # Alimentando a entrada atual ao modelo e obtendo a saída
221
- saida = model(entrada)
222
-
223
- # Pegando o índice do maior valor no último conjunto de logits (log-odds) da saída,
224
- # que é a previsão do modelo para o próximo token
225
- predicted = saida.logits[-1].argmax()
226
-
227
- # Concatenando a previsão atual com a entrada atual.
228
- # Isso servirá como a nova entrada para a próxima iteração.
229
- entrada = torch.cat((entrada, predicted.unsqueeze(0)), dim = 0)
230
-
231
- # Adicionando a previsão atual à lista de soluções e convertendo o tensor em um número Python padrão
232
- solution.append(predicted.cpu().item())
233
-
234
- # Decodificando a lista de soluções para obter a string de saída e retornando-a
235
- return tokenizer.decode(solution)
236
-
237
- # Definindo a função avalia_modelo com dois parâmetros: num_samples e log
238
- def avalia_modelo(num_samples = 1000, log = False):
239
-
240
- # Iniciando um contador para as previsões corretas
241
- correct = 0
242
-
243
- # Loop que itera num_samples vezes
244
- for i in range(num_samples):
245
-
246
- # Obtendo a entrada e o alvo (resposta correta) do i-ésimo exemplo do conjunto de teste
247
- entrada, target = dataset_teste[i]
248
-
249
- # Convertendo os tensores de entrada e alvo em arrays numpy para processamento posterior
250
- entrada = entrada.cpu().numpy()
251
- target = target.cpu().numpy()
252
-
253
- # Decodificando a entrada e o alvo utilizando o tokenizer
254
- entrada = tokenizer.decode(entrada[:sequence_length])
255
- target = tokenizer.decode(target[sequence_length-1:])
256
-
257
- # Gerando a previsão utilizando a função faz_previsao
258
- predicted = faz_previsao(entrada, solution_length = result_length, model = modelo)
259
-
260
- # Se a previsão for igual ao alvo, incrementa o contador de previsões corretas
261
- if target == predicted:
262
- correct += 1
263
- # Se log for True, imprime detalhes do exemplo e a previsão correta
264
- if log:
265
- print(f'Acerto do Modelo: Input: {entrada} Target: {target} Previsão: {predicted}')
266
- else:
267
- # Se log for True, imprime detalhes do exemplo e a previsão errada
268
- if log:
269
- print(f'Erro do Modelo: Input: {entrada} Target: {target} Previsão: {predicted}')
270
-
271
- # Ao final do loop, calcula a acurácia (número de previsões corretas dividido pelo número total de exemplos)
272
- print(f'Acurácia: {correct/num_samples}')
273
-
274
- # Executa a função
275
- avalia_modelo(num_samples = 10, log = True)
276
-
277
- # Executa a função
278
- avalia_modelo(num_samples = 1000, log = False)
279
-
280
- type(modelo)
281
-
282
- modelo.save_pretrained("modelos/modelo_final")
283
-