Spaces:
Sleeping
Sleeping
| # --- | |
| # jupyter: | |
| # jupytext: | |
| # text_representation: | |
| # extension: .py | |
| # format_name: percent | |
| # format_version: '1.3' | |
| # jupytext_version: 1.3.4 | |
| # kernelspec: | |
| # display_name: Python 3 | |
| # language: python | |
| # name: python3 | |
| # --- | |
| import torch | |
| import torch.nn as nn | |
| from torch.nn import functional as F | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| print(device) | |
| block_size = 8 | |
| batch_size = 4 | |
| max_iters = 100000 | |
| learning_rate = 3e-4 | |
| eval_every = 5000 | |
| # %% | |
| with open("shakespeare.txt") as f: | |
| text = f.read() | |
| print(text[:500]) | |
| # %% | |
| chars = sorted(set(text)) | |
| vocab_size = len(chars) | |
| # %% | |
| print(f"Vocab size: {vocab_size}") | |
| print(f"Text length: {len(text)}") | |
| # %% | |
| string_to_int = {ch: i for i, ch in enumerate(chars)} | |
| int_to_string = {i: ch for i, ch in enumerate(chars)} | |
| encode = lambda s: [string_to_int[ch] for ch in s] | |
| decode = lambda x: ''.join([int_to_string[i] for i in x]) | |
| data = torch.tensor(encode(text), dtype=torch.long, device=device) | |
| # %% | |
| n = int(0.8 * len(data)) | |
| train_data = data[:n] | |
| val_data = data[n:] | |
| # %% | |
| def get_batch(split): | |
| data = train_data if split == 'train' else val_data | |
| ix = torch.randint(len(data) - block_size, (batch_size,)) | |
| x = torch.stack([data[i:i+block_size] for i in ix]) | |
| y = torch.stack([data[i+1:i+block_size+1] for i in ix]) | |
| x, y = x.to(device), y.to(device) | |
| return x, y | |
| # %% | |
| x, y = get_batch('train') | |
| # %% | |
| class BigramLanguageModel(nn.Module): | |
| def __init__(self, vocab_size): | |
| super().__init__() | |
| self.token_embedding_table = nn.Embedding(vocab_size, vocab_size) | |
| def forward(self, index, targets=None): | |
| logits = self.token_embedding_table(index) | |
| if targets is None: | |
| loss = None | |
| else: | |
| B, T, C = logits.shape | |
| logits = logits.view(B*T, C) # reshape to what torch.cross_entropy expects | |
| targets = targets.view(B*T) | |
| loss = F.cross_entropy(logits, targets) | |
| return logits, loss | |
| def generate(self, index, max_new_tokens): | |
| # index is (B, T) array of indices in the current context | |
| for _ in range(max_new_tokens): | |
| # get the predictions | |
| logits, loss = self.forward(index) | |
| # focus only on the last time step | |
| logits = logits[:, -1, :] # becomes (B, C) | |
| # apply softmax to get probabilities | |
| probs = F.softmax(logits, dim=-1) # (B, C) | |
| # sample from the distribution | |
| index_next = torch.multinomial(probs, num_samples=1) # (B, 1) | |
| # append sampled index to the running sequence | |
| index = torch.cat((index, index_next), dim=1) # (B, T+1) | |
| return index | |
| # %% | |
| model = BigramLanguageModel(vocab_size).to(device) | |
| context = torch.zeros((1,1), dtype=torch.long, device=device) | |
| generated_chars = decode(model.generate(context, max_new_tokens=100)[0].tolist()) | |
| print(generated_chars) | |
| # %% [markdown] | |
| # | |
| # ### Some common optimizers | |
| # 1. **Mean Squared Error (MSE)**: MSE is a common loss function used in regression problems, where the goal is to predict a continuous output. It measures the average squared difference between the predicted and actual values, and is often used to train neural networks for regression tasks. | |
| # 2. **Gradient Descent (GD):** is an optimization algorithm used to minimize the loss function of a machine learning model. The loss function measures how well the model is able to predict the target variable based on the input features. The idea of GD is to iteratively adjust the model parameters in the direction of the steepest descent of the loss function | |
| # 3. **Momentum**: Momentum is an extension of SGD that adds a \"momentum\" term to the parameter updates. This term helps smooth out the updates and allows the optimizer to continue moving in the right direction, even if the gradient changes direction or varies in magnitude. Momentum is particularly useful for training deep neural networks. | |
| # 4. **RMSprop**: RMSprop is an optimization algorithm that uses a moving average of the squared gradient to adapt the learning rate of each parameter. This helps to avoid oscillations in the parameter updates and can improve convergence in some cases. | |
| # 5. **Adam**: Adam is a popular optimization algorithm that combines the ideas of momentum and RMSprop. It uses a moving average of both the gradient and its squared value to adapt the learning rate of each parameter. Adam is often used as a default optimizer for deep learning models. | |
| # 6. **AdamW**: AdamW is a modification of the Adam optimizer that adds weight decay to the parameter updates. This helps to regularize the model and can improve generalization performance. We will be using the AdamW optimizer as it best suits the properties of the model we will train in this video. | |
| # find more optimizers and details at torch.optim | |
| # %% | |
| optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate) | |
| for iter in range(max_iters): | |
| # sample a batch | |
| xb, yb = get_batch('train') | |
| # evaluate the loss | |
| logits, loss = model.forward(xb, yb) | |
| optimizer.zero_grad(set_to_none=True) | |
| loss.backward() | |
| optimizer.step() | |
| if iter % eval_every == 0: | |
| print(f"Iter {iter}:") | |
| print(loss.item()) | |
| print(loss.item()) | |
| # %% | |
| context = torch.zeros((1,1), dtype=torch.long, device=device) | |
| generated_chars = decode(model.generate(context, max_new_tokens=100)[0].tolist()) | |
| print(generated_chars) | |