paint-brush
Dərin Öyrənmə Üzən Nöqtəli Riyaziyyatda Çalışır. Bəs bu Səhvdirsə?tərəfindən@abhiyanampally_kob9nse8
549 oxunuşlar
549 oxunuşlar

Dərin Öyrənmə Üzən Nöqtəli Riyaziyyatda Çalışır. Bəs bu Səhvdirsə?

tərəfindən 40m2025/02/11
Read on Terminal Reader

Çox uzun; Oxumaq

Loqarifmik Say Sistemi (LNS) Üzən Nöqtə (FP) arifmetikasına alternativ ədədi təmsildir. LNS, müəyyən aparat arxitekturalarında hesablama baxımından daha ucuz ola bilən vurmaları əlavələrə çevirərək, loqarifm miqyasında ədədləri təmsil edir. Bununla belə, LNS-də əlavə və çıxma təxminləri tələb edir, bu da dəqiqliyin azalmasına səbəb olur. MNIST-də sadə, tam qoşulmuş Çox Layer Perceptron hazırlamaq üçün LNS-dən istifadə edirik.
featured image - Dərin Öyrənmə Üzən Nöqtəli Riyaziyyatda Çalışır. Bəs bu Səhvdirsə?
undefined HackerNoon profile picture
0-item
1-item

Dərin öyrənmədə Loqarifmik Say sistemindən (LNS) istifadə etmək fikri ilə ilk dəfə rastlaşdığım zaman maraqlı idim, həm də şübhə ilə yanaşırdım. Çoxumuz kimi, mən də həmişə dərin öyrənmədə ədədi hesablama üçün standart olan Floating-Point (FP) arifmetikası ilə işləmişəm. FP dəqiqlik və diapazon arasında yaxşı tarazlığı təmin edir, lakin o, güzəştlərlə gəlir: daha yüksək yaddaş istifadəsi, artan hesablama mürəkkəbliyi və daha çox enerji istehlakı. Beləliklə, mən təcrübə etmək və özüm görmək qərarına gəldim - MNIST-də sadə, tam qoşulmuş Çox Qatlı Perseptron (MLP) hazırlayarkən LNS FP ilə necə müqayisə olunur?

Niyə LNS-i nəzərdən keçirin?

LNS, müəyyən aparat arxitekturalarında hesablama baxımından daha ucuz ola bilən vurmaları əlavələrə çevirərək, loqarifmik miqyasda ədədləri təmsil edir. Bu səmərəlilik, xüsusilə LNS-də daha mürəkkəb olan əlavə və çıxma əməliyyatları ilə bağlı dəqiqlik bahasına gəlir. Bununla belə, potensial faydalar - azaldılmış yaddaş izi, daha sürətli hesablamalar və daha az enerji istehlakı - məni sınamaq üçün kifayət qədər maraqlı etdi.

Ümumi məlumat: Üzən Nöqtə və Loqarifmik Say Sistemi

Üzən Nöqtə (FP) Nümayəndəliyi

Üzən Nöqtə arifmetikası PyTorch və TensorFlow kimi ən dərin öyrənmə çərçivələrində standart ədədi təmsildir. FP nömrələri var:


  • İşarə biti (müsbət və ya mənfi dəyəri təyin etmək)
  • Göstərici (miqyas amili)
  • Mantis (əhəmiyyətli) (rəqəmin dəqiqliyi)


FP32 (tək dəqiqlik) ədədi dəqiqlik və hesablama səmərəliliyi arasında tarazlıq təklif edərək dərin öyrənmədə geniş istifadə olunur. FP16 və BF16 kimi daha səmərəli formatlar təlimi sürətləndirmək üçün populyarlıq qazanır.

Loqarifmik Say Sistemi (LNS)

LNS, ədədlərin loqarifm kimi saxlandığı alternativ ədədi təsvirdir: [ x = \log_b (y) ] burada ( b ) loqarifm bazasıdır. LNS bir sıra üstünlüklərə malikdir:


  • Vurma toplamaq üçün sadələşdirilmişdir : ( x_1 * x_2 = b^{(\log_b x_1 + \log_b x_2)} )
  • Bölmə çıxmaq üçün sadələşdirilmişdir : ( x_1 / x_2 = b^{(\log_b x_1 - \log_b x_2)} )
  • Eksponensial artım funksiyaları xətti olur


Bununla belə, LNS-də əlavə və çıxma təxminləri tələb edir, bu da dəqiqliyin azalmasına səbəb olur.

LNS Arifmetik Əməliyyatlar

LNS-i daha da araşdırmaq üçün LNS daxili təmsillərindən istifadə edərək toplama, çıxma, vurma və bölmə kimi əsas hesab əməliyyatlarını həyata keçirdim.


 import torch import numpy as np import xlns as xl # Assuming xlns module is installed and provides xlnsnp # Function to convert floating-point numbers to xlns internal representation def float_to_internal(arr): xlns_data = xl.xlnsnp(arr) return xlns_data.nd # Function to convert xlns internal representation back to floating-point numbers def internal_to_float(internal_data): original_numbers = [] for value in internal_data: x = value // 2 s = value % 2 # Use x and s to create xlns object xlns_value = xl.xlns(0) xlns_value.x = x xlns_value.s = s original_numbers.append(float(xlns_value)) return original_numbers # Function to perform LNS addition using internal representation def lns_add_internal(x, y): max_part = torch.maximum(x, y) diff = torch.abs(x - y) adjust_term = torch.log1p(torch.exp(-diff)) return max_part + adjust_term # Function to perform LNS subtraction using internal representation def lns_sub_internal(x, y): return lns_add_internal(x, -y) # Function to perform LNS multiplication using internal representation def lns_mul_internal(x, y): return x + y # Function to perform LNS division using internal representation def lns_div_internal(x, y): return x - y # Input floating-point arrays x_float = [2.0, 3.0] y_float = [-1.0, 0.0] # Convert floating-point arrays to xlns internal representation x_internal = float_to_internal(x_float) y_internal = float_to_internal(y_float) # Create tensors from the internal representation tensor_x_nd = torch.tensor(x_internal, dtype=torch.int64) tensor_y_nd = torch.tensor(y_internal, dtype=torch.int64) # Perform the toy LNS addition on the internal representation result_add_internal = lns_add_internal(tensor_x_nd, tensor_y_nd) # Perform the toy LNS subtraction on the internal representation result_sub_internal = lns_sub_internal(tensor_x_nd, tensor_y_nd) # Perform the toy LNS multiplication on the internal representation result_mul_internal = lns_mul_internal(tensor_x_nd, tensor_y_nd) # Perform the toy LNS division on the internal representation result_div_internal = lns_div_internal(tensor_x_nd, tensor_y_nd) # Convert the internal results back to original floating-point values result_add_float = internal_to_float(result_add_internal.numpy()) result_sub_float = internal_to_float(result_sub_internal.numpy()) result_mul_float = internal_to_float(result_mul_internal.numpy()) result_div_float = internal_to_float(result_div_internal.numpy()) # Convert the results back to PyTorch tensors result_add_tensor = torch.tensor(result_add_float, dtype=torch.float32) result_sub_tensor = torch.tensor(result_sub_float, dtype=torch.float32) result_mul_tensor = torch.tensor(result_mul_float, dtype=torch.float32) result_div_tensor = torch.tensor(result_div_float, dtype=torch.float32) # Print results print("Input x:", x_float) print("Input y:", y_float) print("Addition Result:", result_add_float) print("Addition Result Tensor:", result_add_tensor) print("Subtraction Result:", result_sub_float) print("Subtraction Result Tensor:", result_sub_tensor) print("Multiplication Result:", result_mul_float) print("Multiplication Result Tensor:", result_mul_tensor) print("Division Result:", result_div_float) print("Division Result Tensor:", result_div_tensor)


Budur Loqarifmik Say Sisteminin (LNS) eksperimental tətbiqimin xülasəsi.

1. PyTorch-da Əsas LNS Konsepsiyası və Çətinliklər

LNS-də ədədlər vurma və bölməni toplama və çıxmaya çevirən loqarifmlər kimi təqdim olunur. Bununla belə, bunu PyTorch ilə həyata keçirmək xüsusi problemlər yaradır, çünki PyTorch tensorları daxili olaraq üzən nöqtə təsvirlərini istifadə edir. Bu, bir sıra tələblər yaradır:


  • Hesablamalar zamanı loqarifmik təmsili qoruyun.
  • Rəqəmsal sabitliyi təmin edin.
  • Dönüşümləri diqqətlə idarə edin.
  • İki komponentdən istifadə edərək daxili təmsili idarə edin:
    • x : loqarifmik qiymət.
    • s : işarə biti (0 və ya 1).

2. Daxili təmsilçilik və konversiya

İlk addım üzən nöqtəli nömrələri LNS daxili təmsillərinə çevirməkdir.

 import torch import numpy as np import xl # Hypothetical external LNS library def float_to_internal(arr): xlns_data = xl.xlnsnp(arr) return xlns_data.nd # Convert floating-point arrays to xlns internal representation x_float = np.array([2.0, 3.0]) y_float = np.array([-1.0, 0.0]) x_internal = float_to_internal(x_float) y_internal = float_to_internal(y_float) # Create tensors from the internal representation tensor_x_nd = torch.tensor(x_internal, dtype=torch.int64) tensor_y_nd = torch.tensor(y_internal, dtype=torch.int64)


dtype=torch.int64 dən istifadə çox vacibdir, çünki:

  • Üzən nöqtə yuvarlaqlaşdırma xətaları olmadan dəqiq LNS daxili təqdimatını qoruyur.
  • Həm loqarifmik dəyəri, həm də işarə bitini tək tam ədədə yığır.
  • Gözlənilməyən üzən nöqtə əməliyyatlarının LNS təqdimatını pozmasının qarşısını alır.

3. Əsas Arifmetik Əməliyyatlar

a) vurma

 def lns_mul_internal(x, y): return x + y

LNS-də vurma əlavəyə çevrilir:

  • Əgər a = log(x)b = log(y) , onda log(x×y) = log(x) + log(y) .

b) Bölmə

 def lns_div_internal(x, y): return x - y

Bölmə çıxmaya çevrilir:

  • log(x/y) = log(x) - log(y) .

c) Əlavə

 def lns_add_internal(x, y): max_part = torch.maximum(x, y) diff = torch.abs(x - y) adjust_term = torch.log1p(torch.exp(-diff)) return max_part + adjust_term


Əlavə daha mürəkkəb və ədədi cəhətdən həssasdır, çünki:

  • Bu eksponensial və loqarifmik əməliyyatları əhatə edir.
  • Birbaşa üzən nöqtənin tətbiqi daşqın/aşağıya səbəb ola bilər.
  • Tənlikdən istifadə edir: log(x + y) = log(max(x,y)) + log(1 + exp(log(min(x,y)) - log(max(x,y)))) .
  • Daha yaxşı ədədi sabitlik üçün birbaşa log(1 + x) əvəzinə log1p istifadə edir.

4. Tip Təhlükəsizlik və Dönüşüm İdarəetmə

 def internal_to_float(internal_data): for value in internal_data: x = value // 2 # Integer division s = value % 2 # Integer modulo


Dönüşüm boru kəməri aydın bir ayırma təmin edir:

  1. Float-dan çevirin → LNS daxili təmsili (tam ədədlər).
  2. Tam arifmetikadan istifadə edərək LNS əməliyyatlarını yerinə yetirin.
  3. Yalnız zərurət yarandıqda geri qayıdın.
 # Convert results back to float and tensor result_add_float = internal_to_float(result_add_internal.numpy()) result_add_tensor = torch.tensor(result_add_float, dtype=torch.float32)

5. Əsas Üstünlüklər və Məhdudiyyətlər

Üstünlüklər

  • Vurma və bölmə toplama və çıxma ilə sadələşdirilir .
  • Sabit nöqtəli arifmetika ilə geniş dinamik diapazon .
  • Müəyyən tətbiqlər üçün potensial olaraq daha səmərəlidir .

Məhdudiyyətlər

  • Toplama və çıxma daha mürəkkəb əməliyyatlardır.
  • Üzən nöqtə və LNS arasında çevrilmə yükü .
  • Sıfır və mənfi ədədlər üçün xüsusi rəftar tələb edir .
  • PyTorch tensor uyğunluğu ehtiyatlı tip idarəetmə tələb edir.

6. Optimallaşdırma imkanları

Performansı artırmaq üçün aşağıdakıları edə bilərsiniz:

  1. LNS əməliyyatları üçün fərdi PyTorch autograd funksiyasını həyata keçirin.
  2. LNS-i yerli olaraq dəstəkləyən fərdi tensor növü yaradın.
  3. GPU-da səmərəli LNS əməliyyatları üçün CUDA ləpələrindən istifadə edin.


Mövcud tətbiq praktiki mübadilə edir:

  • Maksimum performansdan daha aydınlığa və davamlılığa üstünlük verir.
  • LNS dəqiqliyini qoruyarkən PyTorch-un mövcud tenzor infrastrukturundan istifadə edir.
  • Diqqətli tip idarəetməsi vasitəsilə ədədi sabitliyi qoruyur.
  • Nümayişlər arasında dönüşümləri minimuma endirir.

7. Məlumat axını nümunəsi

Aşağıdakı addımlar [2.0, 3.0][-1.0, 0.0] nümunə dəyərlərindən istifadə edərək tam boru xəttini nümayiş etdirir:

  1. Giriş floatlarını LNS daxili təmsilinə çevirin.
  2. LNS dəyərlərini saxlamaq üçün tam tensorlar yaradın.
  3. LNS domenində arifmetik əməliyyatları yerinə yetirin.
  4. Nəticələri yenidən üzən nöqtəyə çevirin.
  5. Sonrakı emal üçün son PyTorch tensorlarını yaradın.


Bu tətbiq ədədi sabitliyi və dəqiqliyi qoruyarkən PyTorch-un üzən nöqtəli tenzor sistemi ilə LNS arifmetikası arasındakı boşluğu uğurla aradan qaldırır.


FP və LNS ilə MNIST Rəqəm məlumat dəstində tam əlaqəli MLP-nin hazırlanması

Təcrübə Quraşdırma

Mən həm FP, həm də LNS nümayəndəliklərindən istifadə edərək MNIST verilənlər bazasında tam əlaqəli MLP öyrətdim. Modelin memarlığı sadə idi:

  • Giriş qatı: 784 neyron (düzləşdirilmiş 28x28 şəkillər)
  • Gizli təbəqələr: 256 və 128 neyronlu iki qat, ReLU aktivləşdirmələri
  • Çıxış təbəqəsi: 10 neyron (softmax istifadə edərək hər rəqəm üçün bir)
  • Zərər funksiyası: Çarpaz entropiya
  • Optimizator: Adam


LNS tətbiqi üçün adi PyTorch iş axınımdan kənara çıxmalı oldum. PyTorch-un yerli olaraq dəstəklədiyi FP-dən fərqli olaraq, PyTorch daxili LNS əməliyyatlarını təmin etmir. Mən neyron şəbəkələrində LNS-dən istifadə etməyə imkan verən loqarifmik ədəd təqdimatını və arifmetikanı həyata keçirən xlns adlı GitHub layihəsini tapdım.

PyTorch-da Floating Point MLP

Biz PyTorch istifadə edərək standart FP əsaslı tam qoşulmuş MLP tətbiq etməklə başlayırıq:

 import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms import matplotlib.pyplot as plt import numpy as np import time # For calculating elapsed time # Define the multi-layer perceptron (MLP) model with one hidden layer class MLP(nn.Module): def __init__(self): super(MLP, self).__init__() # Input: 28*28 features; Hidden layer: 100 neurons; Output layer: 10 neurons self.fc1 = nn.Linear(28 * 28, 100) self.relu = nn.ReLU() self.fc2 = nn.Linear(100, 10) self.logsoftmax = nn.LogSoftmax(dim=1) # For stable outputs with NLLLoss def forward(self, x): # Flatten image: (batch_size, 1, 28, 28) -> (batch_size, 784) x = x.view(x.size(0), -1) x = self.fc1(x) x = self.relu(x) x = self.fc2(x) return self.logsoftmax(x) def train_and_validate(num_epochs=5, batch_size=64, learning_rate=0.01, split_ratio=0.8): # Set the device to GPU if available device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print(f"Training on device: {device}") # Transformation for MNIST: convert to tensor and normalize transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) # Load the MNIST training dataset train_dataset_full = torchvision.datasets.MNIST( root='./data', train=True, transform=transform, download=True ) # Split the dataset into training and validation sets n_total = len(train_dataset_full) n_train = int(split_ratio * n_total) n_val = n_total - n_train train_dataset, val_dataset = torch.utils.data.random_split(train_dataset_full, [n_train, n_val]) # Create DataLoaders for training and validation datasets train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=batch_size, shuffle=False) # Initialize the model, loss function, and optimizer; move model to device model = MLP().to(device) criterion = nn.NLLLoss() optimizer = optim.SGD(model.parameters(), lr=learning_rate) # Lists to store training and validation accuracies for each epoch train_accuracies = [] val_accuracies = [] # Record the start time for measuring elapsed time start_time = time.time() # Training loop for epoch in range(num_epochs): model.train() running_loss = 0.0 correct_train = 0 total_train = 0 for inputs, labels in train_loader: # Move inputs and labels to device inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # Compute running loss and training accuracy running_loss += loss.item() * inputs.size(0) _, predicted = torch.max(outputs.data, 1) total_train += labels.size(0) correct_train += (predicted == labels).sum().item() train_accuracy = 100.0 * correct_train / total_train train_accuracies.append(train_accuracy) # Evaluate on validation set model.eval() correct_val = 0 total_val = 0 with torch.no_grad(): for inputs, labels in val_loader: inputs, labels = inputs.to(device), labels.to(device) outputs = model(inputs) _, predicted = torch.max(outputs.data, 1) total_val += labels.size(0) correct_val += (predicted == labels).sum().item() val_accuracy = 100.0 * correct_val / total_val val_accuracies.append(val_accuracy) print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/total_train:.4f}, " f"Train Acc: {train_accuracy:.2f}%, Val Acc: {val_accuracy:.2f}%") # Calculate elapsed time elapsed_time = time.time() - start_time print(f"Training completed in {elapsed_time:.2f} seconds.") # Show sample predictions from the validation set show_predictions(model, val_loader, device) # Optional: plot training and validation accuracies epochs_arr = np.arange(1, num_epochs + 1) plt.figure(figsize=(10, 6)) plt.plot(epochs_arr, train_accuracies, label='Training Accuracy', marker='o') plt.plot(epochs_arr, val_accuracies, label='Validation Accuracy', marker='x') plt.xlabel('Epoch') plt.ylabel('Accuracy (%)') plt.title('Training and Validation Accuracies') plt.legend() plt.grid(True) plt.savefig('pytorch_accuracy.png') plt.show() def show_predictions(model, data_loader, device, num_images=6): """ Displays a few sample images from the data_loader along with the model's predictions. """ model.eval() images_shown = 0 plt.figure(figsize=(12, 8)) # Get one batch of images from the validation dataset for inputs, labels in data_loader: inputs, labels = inputs.to(device), labels.to(device) with torch.no_grad(): outputs = model(inputs) _, predicted = torch.max(outputs, 1) # Loop through the batch and plot images for i in range(inputs.size(0)): if images_shown >= num_images: break # Move the image to cpu and convert to numpy for plotting img = inputs[i].cpu().squeeze() plt.subplot(2, num_images // 2, images_shown + 1) plt.imshow(img, cmap='gray') plt.title(f"Pred: {predicted[i].item()}") plt.axis('off') images_shown += 1 if images_shown >= num_images: break plt.suptitle("Sample Predictions from the Validation Set") plt.tight_layout() plt.show() if __name__ == '__main__': train_and_validate(num_epochs=5, batch_size=64, learning_rate=0.01, split_ratio=0.8)


Bu tətbiq, vurma və əlavələrin FP arifmetikası ilə idarə olunduğu adi dərin öyrənmə boru xəttini izləyir.


Budur, MNIST məlumat dəsti üçün Çox Layer Perseptronun (MLP) bu PyTorch tətbiqi ilə bağlı ətraflı məlumat.

  1. Model Memarlığı (MLP Sinfi):
 class MLP(nn.Module): def __init__(self): super(MLP, self).__init__() self.fc1 = nn.Linear(28 * 28, 100) # First fully connected layer self.relu = nn.ReLU() # Activation function self.fc2 = nn.Linear(100, 10) # Output layer self.logsoftmax = nn.LogSoftmax(dim=1)
  1. İrəli keçid:
 def forward(self, x): x = x.view(x.size(0), -1) # Flatten: (batch_size, 1, 28, 28) -> (batch_size, 784) x = self.fc1(x) # First layer x = self.relu(x) # Activation x = self.fc2(x) # Output layer return self.logsoftmax(x) # Final activation
  1. Təlim Quraşdırma:
 def train_and_validate(num_epochs=5, batch_size=64, learning_rate=0.01, split_ratio=0.8): device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # Data preprocessing transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) # Normalize to [-1, 1] ])

Əsas komponentlər:

  • Cihaz seçimi vasitəsilə GPU dəstəyi

  • Daha yaxşı təlim üçün məlumatların normallaşdırılması

  • Konfiqurasiya edilə bilən hiperparametrlər


  1. Dataset Management:
 train_dataset_full = torchvision.datasets.MNIST( root='./data', train=True, transform=transform, download=True ) # Split into train/validation n_train = int(split_ratio * n_total) train_dataset, val_dataset = torch.utils.data.random_split(train_dataset_full, [n_train, n_val])
  • MNIST verilənlər bazası mövcud deyilsə, endirir

  • Məlumatları təlim (80%) və doğrulama (20%) dəstlərinə bölür


  1. Təlim dövrəsi:
 for epoch in range(num_epochs): model.train() for inputs, labels in train_loader: inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() # Clear gradients outputs = model(inputs) # Forward pass loss = criterion(outputs, labels)# Calculate loss loss.backward() # Backward pass optimizer.step() # Update weights

Klassik məşq proseduru:

  • Sıfır gradient

  • İrəli ötürmə

  • Zərərlərin hesablanması

  • Geri ötürmə

  • Çəki yeniləmələri


  1. Doğrulama:
 model.eval() with torch.no_grad(): for inputs, labels in val_loader: outputs = model(inputs) _, predicted = torch.max(outputs.data, 1) total_val += labels.size(0) correct_val += (predicted == labels).sum().item()

Əsas xüsusiyyətlər:

  • Model qiymətləndirmə rejiminə təyin edildi

  • Qradiyent hesablamasına ehtiyac yoxdur

  • Dəqiqliyin hesablanması


  1. Vizuallaşdırma:
 def show_predictions(model, data_loader, device, num_images=6): model.eval() plt.figure(figsize=(12, 8)) # Display predictions vs actual labels
  • Doğrulama dəstindən nümunə proqnozlarını göstərir

  • Keyfiyyətli qiymətləndirmə üçün faydalıdır


  1. Performans İzləmə:
 # Training metrics train_accuracies.append(train_accuracy) val_accuracies.append(val_accuracy) # Plot learning curves plt.plot(epochs_arr, train_accuracies, label='Training Accuracy') plt.plot(epochs_arr, val_accuracies, label='Validation Accuracy')
  • Təlim və doğrulama dəqiqliyini izləyir

  • Öyrənmə əyrilərini tərtib edir

  • Təlim vaxtını ölçür


Bu, ənənəvi üzən nöqtəli hesabdan istifadə edərək dərin öyrənmə boru kəmərinin bütün standart komponentlərini tətbiq etdiyi üçün LNS-əsaslı tətbiqlərlə müqayisə üçün möhkəm zəmin yaradır.

Loqarifmik Say Sistemi (LNS) MLP

LNS üçün xlns kitabxanasından istifadə etməliyik. FP-dən fərqli olaraq, LNS vurma-ağır əməliyyatları loqarifmik sahədə əlavə ilə əvəz edir. Bununla belə, PyTorch bunu yerli olaraq dəstəkləmir, ona görə də lazım olduqda LNS əməliyyatlarını əl ilə tətbiq etməliyik.

 import numpy as np import matplotlib.pyplot as plt import os import time import argparse import xlns as xl from tensorflow.keras.datasets import mnist # Use Keras's MNIST loader # If you are using fractional normalized LNS, make sure the following are uncommented import xlnsconf.xlnsudFracnorm xlnsconf.xlnsudFracnorm.ilog2 = xlnsconf.xlnsudFracnorm.ipallog2 xlnsconf.xlnsudFracnorm.ipow2 = xlnsconf.xlnsudFracnorm.ipalpow2 # Set global parameter in xlns xl.xlnssetF(10) def softmax(inp): max_vals = inp.max(axis=1) max_vals = xl.reshape(max_vals, (xl.size(max_vals), 1)) u = xl.exp(inp - max_vals) v = u.sum(axis=1) v = v.reshape((xl.size(v), 1)) u = u / v return u def main(main_params): print("arbitrary base np LNS. Also xl.hstack, xl routines in softmax") print("testing new softmax and * instead of @ for delta") print("works with type " + main_params['type']) is_training = bool(main_params['is_training']) leaking_coeff = float(main_params['leaking_coeff']) batchsize = int(main_params['minibatch_size']) lr = float(main_params['learning_rate']) num_epoch = int(main_params['num_epoch']) _lambda = float(main_params['lambda']) ones = np.array(list(np.ones((batchsize, 1)))) if is_training: # Load the MNIST dataset from Keras (x_train, y_train), (x_test, y_test) = mnist.load_data() # Normalize images to [0, 1] x_train = x_train.astype(np.float64) / 255.0 x_test = x_test.astype(np.float64) / 255.0 # One-hot encode the labels (assume 10 classes for MNIST digits 0-9) num_classes = 10 y_train = np.eye(num_classes)[y_train] y_test = np.eye(num_classes)[y_test] # Flatten the images from (28, 28) to (784,) x_train = x_train.reshape(x_train.shape[0], -1) x_test = x_test.reshape(x_test.shape[0], -1) # Use a portion of the training data for validation (the 'split' index) split = int(main_params['split']) x_val = x_train[split:] y_val = y_train[split:] x_train = x_train[:split] y_train = y_train[:split] # If available, load pretrained weights; otherwise, initialize new random weights. if os.path.isfile("./weightin.npz"): print("using ./weightin.npz") randfile = np.load("./weightin.npz", "r") W1 = randfile["W1"] W2 = randfile["W2"] randfile.close() else: print("using new random weights") # Note: The input layer now has 785 neurons (784 features + 1 bias). W1 = np.array(list(np.random.normal(0, 0.1, (785, 100)))) # The first hidden layer has 100 neurons; add bias so 101 W2 = np.array(list(np.random.normal(0, 0.1, (101, 10)))) np.savez_compressed("./weightout.npz", W1=W1, W2=W2) delta_W1 = np.array(list(np.zeros(W1.shape))) delta_W2 = np.array(list(np.zeros(W2.shape))) # Convert weights to desired type (xlns variants or float) if main_params['type'] == 'xlnsnp': lnsW1 = xl.xlnsnp(np.array(xl.xlnscopy(list(W1)))) lnsW2 = xl.xlnsnp(np.array(xl.xlnscopy(list(W2)))) lnsones = xl.xlnsnp(np.array(xl.xlnscopy(list(np.ones((batchsize, 1)))))) lnsdelta_W1 = xl.xlnsnp(np.array(xl.xlnscopy(list(np.zeros(W1.shape))))) lnsdelta_W2 = xl.xlnsnp(np.array(xl.xlnscopy(list(np.zeros(W2.shape))))) elif main_params['type'] == 'xlnsnpv': lnsW1 = xl.xlnsnpv(np.array(xl.xlnscopy(list(W1))), 6) lnsW2 = xl.xlnsnpv(np.array(xl.xlnscopy(list(W2))), 6) lnsones = xl.xlnsnpv(np.array(xl.xlnscopy(list(np.ones((batchsize, 1)))))) lnsdelta_W1 = xl.xlnsnpv(np.array(xl.xlnscopy(list(np.zeros(W1.shape))))) lnsdelta_W2 = xl.xlnsnpv(np.array(xl.xlnscopy(list(np.zeros(W2.shape))))) elif main_params['type'] == 'xlnsnpb': lnsW1 = xl.xlnsnpb(np.array(xl.xlnscopy(list(W1))), 2**2**-6) lnsW2 = xl.xlnsnpb(np.array(xl.xlnscopy(list(W2))), 2**2**-6) lnsones = xl.xlnsnpb(np.array(xl.xlnscopy(list(np.ones((batchsize, 1))))), 2**2**-xl.xlnsF) lnsdelta_W1 = xl.xlnsnpb(np.array(xl.xlnscopy(list(np.zeros(W1.shape)))), 2**2**-xl.xlnsF) lnsdelta_W2 = xl.xlnsnpb(np.array(xl.xlnscopy(list(np.zeros(W2.shape)))), 2**2**-xl.xlnsF) elif main_params['type'] == 'xlns': lnsW1 = np.array(xl.xlnscopy(list(W1))) lnsW2 = np.array(xl.xlnscopy(list(W2))) lnsones = np.array(xl.xlnscopy(list(np.ones((batchsize, 1))))) lnsdelta_W1 = np.array(xl.xlnscopy(list(np.zeros(W1.shape)))) lnsdelta_W2 = np.array(xl.xlnscopy(list(np.zeros(W2.shape)))) elif main_params['type'] == 'xlnsud': lnsW1 = np.array(xl.xlnscopy(list(W1), xl.xlnsud)) lnsW2 = np.array(xl.xlnscopy(list(W2), xl.xlnsud)) lnsones = np.array(xl.xlnscopy(list(np.ones((batchsize, 1))), xl.xlnsud)) lnsdelta_W1 = np.array(xl.xlnscopy(list(np.zeros(W1.shape)), xl.xlnsud)) lnsdelta_W2 = np.array(xl.xlnscopy(list(np.zeros(W2.shape)), xl.xlnsud)) elif main_params['type'] == 'xlnsv': lnsW1 = np.array(xl.xlnscopy(list(W1), xl.xlnsv, 6)) lnsW2 = np.array(xl.xlnscopy(list(W2), xl.xlnsv, 6)) lnsones = np.array(xl.xlnscopy(list(np.ones((batchsize, 1))), xl.xlnsv)) lnsdelta_W1 = np.array(xl.xlnscopy(list(np.zeros(W1.shape)), xl.xlnsv)) lnsdelta_W2 = np.array(xl.xlnscopy(list(np.zeros(W2.shape)), xl.xlnsv)) elif main_params['type'] == 'xlnsb': lnsW1 = np.array(xl.xlnscopy(list(W1), xl.xlnsb, 2**2**-6)) lnsW2 = np.array(xl.xlnscopy(list(W2), xl.xlnsb, 2**2**-6)) lnsones = np.array(xl.xlnscopy(list(np.ones((batchsize, 1))), xl.xlnsb, 2**2**-xl.xlnsF)) lnsdelta_W1 = np.array(xl.xlnscopy(list(np.zeros(W1.shape)), xl.xlnsb, 2**2**-xl.xlnsF)) lnsdelta_W2 = np.array(xl.xlnscopy(list(np.zeros(W2.shape)), xl.xlnsb, 2**2**-xl.xlnsF)) elif main_params['type'] == 'float': lnsW1 = np.array(list(W1)) lnsW2 = np.array(list(W2)) lnsones = np.array(list(np.ones((batchsize, 1)))) lnsdelta_W1 = np.array(list(np.zeros(W1.shape))) lnsdelta_W2 = np.array(list(np.zeros(W2.shape))) performance = {} performance['lnsacc_train'] = np.zeros(num_epoch) performance['lnsacc_val'] = np.zeros(num_epoch) start_time = time.process_time() # Training loop for epoch in range(num_epoch): print('At Epoch %d:' % (1 + epoch)) # Loop through training batches for mbatch in range(int(split / batchsize)): start = mbatch * batchsize x = np.array(x_train[start:(start + batchsize)]) y = np.array(y_train[start:(start + batchsize)]) # At this point, each x is already flattened (batchsize x 784) # Conversion based on type if main_params['type'] == 'xlnsnp': lnsx = xl.xlnsnp(np.array(xl.xlnscopy(np.array(x, dtype=np.float64)))) lnsy = xl.xlnsnp(np.array(xl.xlnscopy(np.array(y, dtype=np.float64)))) elif main_params['type'] == 'xlnsnpv': lnsx = xl.xlnsnpv(np.array(xl.xlnscopy(np.array(x, dtype=np.float64)))) lnsy = xl.xlnsnpv(np.array(xl.xlnscopy(np.array(y, dtype=np.float64)))) elif main_params['type'] == 'xlnsnpb': lnsx = xl.xlnsnpb(np.array(xl.xlnscopy(np.array(x, dtype=np.float64))), 2**2**-xl.xlnsF) lnsy = xl.xlnsnpb(np.array(xl.xlnscopy(np.array(y, dtype=np.float64))), 2**2**-xl.xlnsF) elif main_params['type'] == 'xlns': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64))) lnsy = np.array(xl.xlnscopy(np.array(y, dtype=np.float64))) elif main_params['type'] == 'xlnsud': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsud)) lnsy = np.array(xl.xlnscopy(np.array(y, dtype=np.float64), xl.xlnsud)) elif main_params['type'] == 'xlnsv': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsv)) lnsy = np.array(xl.xlnscopy(np.array(y, dtype=np.float64), xl.xlnsv)) elif main_params['type'] == 'xlnsb': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsv, 2**2**-xl.xlnsF)) lnsy = np.array(xl.xlnscopy(np.array(y, dtype=np.float64), xl.xlnsv, 2**2**-xl.xlnsF)) elif main_params['type'] == 'float': lnsx = np.array(x, dtype=np.float64) lnsy = np.array(y, dtype=np.float64) # Concatenate the bias "ones" with input features for the first layer lnss1 = xl.hstack((lnsones, lnsx)) @ lnsW1 lnsmask = (lnss1 > 0) + (leaking_coeff * (lnss1 < 0)) lnsa1 = lnss1 * lnsmask lnss2 = xl.hstack((lnsones, lnsa1)) @ lnsW2 lnsa2 = softmax(lnss2) lnsgrad_s2 = (lnsa2 - lnsy) / batchsize lnsgrad_a1 = lnsgrad_s2 @ xl.transpose(lnsW2[1:]) lnsdelta_W2 = xl.transpose(xl.hstack((lnsones, lnsa1))) * lnsgrad_s2 lnsgrad_s1 = lnsmask * lnsgrad_a1 lnsdelta_W1 = xl.transpose(xl.hstack((lnsones, lnsx))) * lnsgrad_s1 lnsW2 -= (lr * (lnsdelta_W2 + (_lambda * lnsW2))) lnsW1 -= (lr * (lnsdelta_W1 + (_lambda * lnsW1))) print('#= ', split, ' batch=', batchsize, ' lr=', lr) lnscorrect_count = 0 # Evaluate accuracy on training set for mbatch in range(int(split / batchsize)): start = mbatch * batchsize x = x_train[start:(start + batchsize)] y = y_train[start:(start + batchsize)] if main_params['type'] == 'xlnsnp': lnsx = xl.xlnsnp(np.array(xl.xlnscopy(np.array(x, dtype=np.float64)))) elif main_params['type'] == 'xlnsnpv': lnsx = xl.xlnsnpv(np.array(xl.xlnscopy(np.array(x, dtype=np.float64)))) elif main_params['type'] == 'xlnsnpb': lnsx = xl.xlnsnpb(np.array(xl.xlnscopy(np.array(x, dtype=np.float64))), 2**2**-xl.xlnsF) elif main_params['type'] == 'xlns': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64))) elif main_params['type'] == 'xlnsud': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsud)) elif main_params['type'] == 'xlnsv': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsv)) elif main_params['type'] == 'xlnsb': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsv, 2**2**-xl.xlnsF)) elif main_params['type'] == 'float': lnsx = np.array(x, dtype=np.float64) lnss1 = xl.hstack((lnsones, lnsx)) @ lnsW1 lnsmask = (lnss1 > 0) + (leaking_coeff * (lnss1 < 0)) lnsa1 = lnss1 * lnsmask lnss2 = xl.hstack((lnsones, lnsa1)) @ lnsW2 lnscorrect_count += np.sum(np.argmax(y, axis=1) == xl.argmax(lnss2, axis=1)) lnsaccuracy = lnscorrect_count / split print("train-set accuracy at epoch %d: %f" % (1 + epoch, lnsaccuracy)) performance['lnsacc_train'][epoch] = 100 * lnsaccuracy lnscorrect_count = 0 # Evaluate on the validation set for mbatch in range(int(split / batchsize)): start = mbatch * batchsize x = x_val[start:(start + batchsize)] y = y_val[start:(start + batchsize)] if main_params['type'] == 'xlnsnp': lnsx = xl.xlnsnp(np.array(xl.xlnscopy(np.array(x, dtype=np.float64)))) elif main_params['type'] == 'xlnsnpv': lnsx = xl.xlnsnpv(np.array(xl.xlnscopy(np.array(x, dtype=np.float64)))) elif main_params['type'] == 'xlnsnpb': lnsx = xl.xlnsnpb(np.array(xl.xlnscopy(np.array(x, dtype=np.float64))), 2**2**-xl.xlnsF) elif main_params['type'] == 'xlns': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64))) elif main_params['type'] == 'xlnsud': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsud)) elif main_params['type'] == 'xlnsv': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsv)) elif main_params['type'] == 'xlnsb': lnsx = np.array(xl.xlnscopy(np.array(x, dtype=np.float64), xl.xlnsv, 2**2**-xl.xlnsF)) elif main_params['type'] == 'float': lnsx = np.array(x, dtype=np.float64) lnss1 = xl.hstack((lnsones, lnsx)) @ lnsW1 lnsmask = (lnss1 > 0) + (leaking_coeff * (lnss1 < 0)) lnsa1 = lnss1 * lnsmask lnss2 = xl.hstack((lnsones, lnsa1)) @ lnsW2 lnscorrect_count += np.sum(np.argmax(y, axis=1) == xl.argmax(lnss2, axis=1)) lnsaccuracy = lnscorrect_count / split print("Val-set accuracy at epoch %d: %f" % (1 + epoch, lnsaccuracy)) performance['lnsacc_val'][epoch] = 100 * lnsaccuracy print("elapsed time=" + str(time.process_time() - start_time)) fig = plt.figure(figsize=(16, 9)) ax = fig.add_subplot(111) x_axis = range(1, 1 + performance['lnsacc_train'].size) ax.plot(x_axis, performance['lnsacc_train'], 'y') ax.plot(x_axis, performance['lnsacc_val'], 'm') ax.set_xlabel('Number of Epochs') ax.set_ylabel('Accuracy') plt.suptitle(main_params['type'] + ' ' + str(split) + ' Validation and Training MNIST Accuracies F=' + str(xl.xlnsF), fontsize=14) ax.legend(['train', 'validation']) plt.grid(which='both', axis='both', linestyle='-.') plt.savefig('genericaccuracy.png') plt.show() # Now, show predictions on a few test images num_examples = 5 # Number of test images to display selected_indices = np.arange(num_examples) # choose the first few images for demo x_sample = x_test[selected_indices] y_sample = y_test[selected_indices] # For prediction, create a bias vector matching the sample size ones_sample = np.ones((x_sample.shape[0], 1)) z1_sample = np.hstack((ones_sample, x_sample)) @ lnsW1 mask_sample = (z1_sample > 0) + (leaking_coeff * (z1_sample < 0)) a1_sample = z1_sample * mask_sample z2_sample = np.hstack((ones_sample, a1_sample)) @ lnsW2 pred_probs = softmax(z2_sample) predictions = np.argmax(pred_probs, axis=1) true_labels = np.argmax(y_sample, axis=1) # Plot each test image along with its prediction and true label plt.figure(figsize=(10, 2)) for i in range(num_examples): plt.subplot(1, num_examples, i + 1) # Reshape the flattened image back to 28x28 for display plt.imshow(x_sample[i].reshape(28, 28), cmap='gray') plt.title(f"Pred: {predictions[i]}\nTrue: {true_labels[i]}") plt.axis('off') plt.tight_layout() plt.show() if __name__ == '__main__': # In a Kaggle notebook, set parameters manually using a dictionary. main_params = { 'is_training': True, 'split': 50, 'learning_rate': 0.01, 'lambda': 0.000, 'minibatch_size': 1, 'num_epoch': 5, 'leaking_coeff': 0.0078125, 'type': 'float' } main(main_params)


Mən sizə MNIST rəqəm təsnifatı üçün Loqarifmik Say Sistemini (LNS) Çox Qatlı Perseptronu (MLP) tətbiq edən bu kodla tanış olacağam. İcazə verin onu əsas bölmələrə ayırım:


  1. Quraşdırma və İdxal:
  • Kod loqarifmik say sistemi əməliyyatları üçün xlns kitabxanasından istifadə edir

  • Müxtəlif dəqiqlik və performans mübadilələri üçün çoxlu LNS variantları (xlnsnp, xlnsnpv, xlnsud və s.) təklif edir.

  • MNIST verilənlər bazası Keras vasitəsilə yüklənir


  1. Əsas funksiyalar:
 def softmax(inp): max_vals = inp.max(axis=1) max_vals = xl.reshape(max_vals, (xl.size(max_vals), 1)) u = xl.exp(inp - max_vals) v = u.sum(axis=1) v = v.reshape((xl.size(v), 1)) u = u / v return u

Bu, LNS əməliyyatları üçün uyğunlaşdırılmış ədədi sabit softmax tətbiqidir.


  1. Şəbəkə Memarlığı:
  • Giriş təbəqəsi: 784 neyron (28x28 yastı MNIST şəkilləri) + 1 meyl = 785

  • Gizli təbəqə: 100 neyron + 1 meyl = 101

  • Çıxış qatı: 10 neyron (hər rəqəmə bir)


  1. Çəki başlanğıcı:
  • Çəkilər ya fayldan yüklənir ("weightin.npz") və ya təsadüfi olaraq işə salınır

  • Təsadüfi çəkilər orta=0, std=0.1 olan normal paylanmadan istifadə edir

  • Fərqli LNS variantları fərqli başlatma üsullarını tələb edir (xlnsnp, xlnsnpv və s.)


  1. Təlim dövrəsi:
 for epoch in range(num_epoch): for mbatch in range(int(split / batchsize)): # Forward pass lnss1 = xl.hstack((lnsones, lnsx)) @ lnsW1 lnsmask = (lnss1 > 0) + (leaking_coeff * (lnss1 < 0)) lnsa1 = lnss1 * lnsmask lnss2 = xl.hstack((lnsones, lnsa1)) @ lnsW2 lnsa2 = softmax(lnss2) # Backward pass lnsgrad_s2 = (lnsa2 - lnsy) / batchsize lnsgrad_a1 = lnsgrad_s2 @ xl.transpose(lnsW2[1:]) lnsdelta_W2 = xl.transpose(xl.hstack((lnsones, lnsa1))) * lnsgrad_s2 lnsgrad_s1 = lnsmask * lnsgrad_a1 lnsdelta_W1 = xl.transpose(xl.hstack((lnsones, lnsx))) * lnsgrad_s1


Təlimin əsas aspektləri:

  • Sızdıran ReLU aktivasiyasından istifadə edir (leaking_coeff tərəfindən idarə olunur)

  • LNS əməliyyatları ilə standart geri yayılma tətbiq edir

  • L2 nizamlanması daxildir (lambda parametri)

  • Öyrənmə dərəcəsi "lr" ilə gradient enişindən istifadə edərək çəkiləri yeniləyir


  1. Qiymətləndirmə:
  • Həm təlim, həm də doğrulama dəqiqliyini izləyir

  • Dövrlər üzrə dəqiqliyi göstərən öyrənmə əyrilərini tərtib edir

  • Test şəkillərində nümunə proqnozları göstərir


  1. Hiperparametrlər:
 main_params = { 'is_training': True, 'split': 50, 'learning_rate': 0.01, 'lambda': 0.000, 'minibatch_size': 1, 'num_epoch': 5, 'leaking_coeff': 0.0078125, 'type': 'float' }
  • Mini-batch gradient enişindən istifadə edir (defolt partiya ölçüsü = 1)

  • Doğrulama dəstinin bölünməsi vasitəsilə erkən dayandırmağı həyata keçirir

  • Leaky ReLU əmsalı 0,0078125 olaraq təyin edilib


  1. Vizuallaşdırma:
  • Təlim və doğrulama dəqiqliyini göstərən süjetlər yaradır
  • Proqnozlar və həqiqi etiketlərlə nümunə test şəkillərini göstərir
  • Dəqiqlik süjetini 'genericaccuracy.png' olaraq saxlayır


Burada əsas yenilik, vurmaları log domenindəki əlavələrlə əvəz edən, müəyyən aparat tətbiqləri üçün potensial olaraq daha yaxşı hesablama səmərəliliyini təklif edən LNS arifmetikasının istifadəsidir. Kod müxtəlif dəqiqlik-performans mübadilələrinə imkan verən çoxsaylı LNS variantlarını dəstəkləyir.

Əsas Performans Müqayisəsi

Üzən Nöqtəli Model Performansı

 Training on device: cuda Epoch [1/5], Loss: 0.8540, Train Acc: 79.60%, Val Acc: 88.22% Epoch [2/5], Loss: 0.3917, Train Acc: 88.97%, Val Acc: 89.92% Epoch [3/5], Loss: 0.3380, Train Acc: 90.29%, Val Acc: 90.60% Epoch [4/5], Loss: 0.3104, Train Acc: 90.96%, Val Acc: 91.12% Epoch [5/5], Loss: 0.2901, Train Acc: 91.60%, Val Acc: 91.62% Training completed in 57.76 seconds. 

FP əsaslı MLP modelinin proqnozları

FP əsaslı MLP Modeli üçün Təlim və Qiymətləndirmə Əyrisi


Loqarifmik Say Sistemi Modelinin Performansı

 At Epoch 1: train-set accuracy at epoch 1: 52.00% Val-set accuracy at epoch 1: 24.00% At Epoch 2: train-set accuracy at epoch 2: 74.00% Val-set accuracy at epoch 2: 40.00% At Epoch 3: train-set accuracy at epoch 3: 86.00% Val-set accuracy at epoch 3: 58.00% At Epoch 4: train-set accuracy at epoch 4: 94.00% Val-set accuracy at epoch 4: 70.00% At Epoch 5: train-set accuracy at epoch 5: 96.00% Val-set accuracy at epoch 5: 68.00% elapsed time = 0.35 seconds. 

LNS əsaslı MLP modelinin proqnozları

LNS əsaslı MLP Modeli üçün Təlim və Qiymətləndirmə Əyrisi


FP və LNS: Əsas Müqayisələr

Aspekt

Üzən nöqtə (FP)

Loqarifmik Say Sistemi (LNS)

Təlim vaxtı

57,76 s

0,35 s

Qatar Dəqiqliyi

91,60%

96.00%

Val Dəqiqliyi

91,62%

68.00%

Dəqiqlik

Yüksək

Aşağı (təxmin etmə xətaları)

Yaddaş Effektivliyi

Daha yüksək istifadə

Aşağı yaddaş izi

Vurmanın idarə edilməsi

Doğma çoxalma

Əlavə əsaslı sadələşdirmələr

Nəticə

Loqarifmik Say Sistemi (LNS)Üzən Nöqtə (FP) arifmetikası arasındakı mübadilələr neyron şəbəkələri üçün aparat-proqram təminatının birgə dizaynında maraqlı bir nümunə təqdim edir. LNS müəyyən sahələrdə əhəmiyyətli üstünlüklər təqdim edərkən:

Təlim Sürəti

  • Günlük domenində vurmanı əlavə ilə əvəz edir
  • Mürəkkəb əməliyyatları daha sadə hesaba endirir
  • Neyron şəbəkələrində matrislərin çoxaldılması üçün xüsusilə effektivdir
  • Bəzi tətbiqlərdə 2-3x sürətlənmə əldə edə bilər

Yaddaşın Faydaları

  • Adətən nömrələri təmsil etmək üçün daha az bit tələb olunur
  • Ağırlıqları və aktivləşdirmələri daha səmərəli şəkildə sıxışdıra bilər
  • Yaddaş genişliyi tələblərini azaldır
  • Yaddaş girişi üçün aşağı enerji istehlakı


Bununla belə, dəqiqliklə bağlı problemlər əhəmiyyətlidir:

  • Kiçik dəyərlərin yığılması zamanı dəqiqlik itkisi
  • Sıfıra çox yaxın rəqəmləri təmsil etməkdə çətinlik
  • Qradient hesablamalarında potensial qeyri-sabitlik
  • Diqqətli hiperparametr tənzimlənməsi tələb oluna bilər

Gələcək istiqamətlər

Bir neçə perspektivli yanaşma LNS-nin tətbiqini artıra bilər:

1. Layer-Xüsusi Arifmetika

  • Həssas təbəqələr üçün FP istifadə edin (son təsnifat kimi)
  • Hesablama tələb edən gizli təbəqələrdə LNS tətbiq edin
  • Rəqəm tələblərinə əsasən dinamik olaraq keçid

2. Precision-Adaptive Computing

  • Sabitlik üçün FP ilə məşqə başlayın
  • Ağırlıqlar yaxınlaşdıqca tədricən LNS-ə keçin
  • Kritik yolları daha yüksək dəqiqliklə qoruyun

3. Hardware Co-Dizayn

  • Həm FP, həm də LNS vahidləri ilə fərdi sürətləndiricilər
  • Arifmetik növlər arasında ağıllı planlaşdırma
  • Hər bir format üçün xüsusi yaddaş iyerarxiyası

4. Alqoritmik İnnovasiyalar

  • LNS üçün optimallaşdırılmış yeni aktivləşdirmə funksiyaları
  • Sabitliyi qoruyan dəyişdirilmiş optimallaşdırma alqoritmləri
  • Hibrid nömrə təmsilləri

Potensial PyTorch Dəstəyi

LNS-ni dərin öyrənmə çərçivələrinə inteqrasiya etmək üçün aşağıdakılar araşdırıla bilər:

1. Xüsusi Autograd Funksiyaları

  • LNS əməliyyatlarını fərdi avtograd funksiyaları kimi həyata keçirin
  • Günlük domenində gradient hesablamasını qoruyun
  • Sürətləndirmə üçün səmərəli CUDA ləpələrini təmin edin

2. Nömrə Tipi Genişləndirmələr

  • Doğma LNS tensor növlərini əlavə edin
  • Giriş domenində əsas əməliyyatları (*+, -, , / ) həyata keçirin
  • Üzən nöqtəyə / nöqtədən çevirmə yardım proqramlarını təmin edin

3. Layer Modifikasiyaları

  • Ümumi təbəqələrin LNS versiyalarını yaradın (Linear, Conv2d)
  • LNS hesablaması üçün geriyə keçidləri optimallaşdırın
  • Qarışıq dəqiq təlimi dəstəkləyin


Dərin öyrənmə icması bu imkanları əsas çərçivələrə inteqrasiya etməklə daha səmərəli, aşağı gücə malik və yüksək sürətli neyroşəbəkələrə imkan yarada bilər.


Ədədi dəqiqlik və hesablama səmərəliliyi arasındakı tarazlıq haqqında fikirləriniz necədir? LNS-nin xüsusilə faydalı ola biləcəyi xüsusi istifadə halları ilə qarşılaşmısınızmı?


Bu haqda fikirlərinizi bildirin.

İstinadlar


[1] G. Alsuhli, et al., “Number Systems for Deep Neural Network Architectures: A Survey,” arXiv:2307.05035 , 2023.

[2] M. Arnold, E. Chester, et al., "Yalnız təxmini masasız LNS ALU istifadə edərək neyron şəbəkələrinin təlimi." 31-ci Beynəlxalq Tətbiqə Xüsusi Sistemlər, Arxitekturalar və Prosessorlar Konfransı, IEEE , 2020, səh. 69–72. DOI

[3] O. Kosheleva, et al., “Logarifmic Number System Is Optimal for AI Computations: Theorical Explanation of Empirical Success,” Paper

[4] D. Miyashita, et al., “Convolutional Neural Networks using Logarithmic Data Representation”, arXiv:1603.01025 , Mart 2016.

[5] J. Zhao et al., “LNS-Madam: Multiplicative Weight Update istifadə edərək Logarifmik Say sistemində Low-Precision Training,” IEEE Transactions on Computers , cild. 71, yox. 12, səh. 3179–3190, dekabr 2022. DOI