Мен логарифмдік санау жүйесін (LNS) терең оқытуда пайдалану идеясын алғаш рет кездестіргенде, мені қызықтырды, бірақ сонымен бірге күмәндандым. Көпшілігіміз сияқты мен әрқашан терең оқытудағы сандық есептеу стандарты болып табылатын Floating-Point (FP) арифметикасымен жұмыс істедім. FP дәлдік пен диапазон арасындағы жақсы тепе-теңдікті қамтамасыз етеді, бірақ ол айырбастаулармен бірге келеді: жадты жоғары пайдалану, есептеу күрделілігінің жоғарылауы және қуатты тұтыну. Сонымен, мен тәжірибе жасап, өз көзіммен көруді шештім — MNIST жүйесінде қарапайым толық қосылған көп қабатты перцептронды (MLP) жаттықтыру кезінде LNS FP-мен қалай салыстырылады? Неліктен LNS туралы ойлану керек? LNS логарифмдік шкаладағы сандарды көрсетеді, көбейтуді қосуға түрлендіреді, бұл белгілі бір аппараттық архитектураларда есептеу жағынан арзанырақ болуы мүмкін. Бұл тиімділік дәлдік құнына, әсіресе LNS жүйесінде күрделірек болатын қосу және алу операцияларына байланысты. Дегенмен, әлеуетті артықшылықтар — жад ізін азайту, жылдам есептеулер және аз қуат тұтыну — мені оны сынап көру үшін қызықтырды. Фон: Қалқымалы нүкте және логарифмдік санау жүйесі Floating Point (FP) ұсыну Қалқымалы нүкте арифметикасы PyTorch және TensorFlow сияқты терең оқыту жүйелерінің көпшілігінде стандартты сандық көрініс болып табылады. FP нөмірлері бар: (оң немесе теріс мәнді анықтау) Белгі биті (масштабтау коэффициенті) Көрсеткіш (санның дәлдігі) Мантисса (мәні) FP32 (бір дәлдік) сандық дәлдік пен есептеу тиімділігі арасындағы тепе-теңдікті қамтамасыз ететін терең оқытуда жиі қолданылады. FP16 және BF16 сияқты тиімдірек пішімдері жаттығуды жеделдету үшін танымал болуда. Логарифмдік санау жүйесі (LNS) LNS — сандар логарифмдер ретінде сақталатын балама сандық көрініс: [ x = \log_b (y) ] мұндағы ( b ) логарифм негізі. LNS бірнеше артықшылықтары бар: : ( x_1 * x_2 = b^{(\log_b x_1 + \log_b x_2)} ) Көбейту қосуға оңайлатылған : ( x_1 / x_2 = b^{(\log_b x_1 - \log_b x_2)} ) Бөлу азайтуға оңайлатылған Экспоненциалды өсу функциялары сызықты болады Дегенмен, LNS жүйесінде қосу және азайту дәлдіктің төмендеуіне әкелетін жуықтауларды қажет етеді. LNS арифметикалық амалдары LNS-ті әрі қарай зерттеу үшін мен LNS ішкі көріністерін пайдаланып қосу, алу, көбейту және бөлу сияқты негізгі арифметикалық амалдарды орындадым. 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) Міне, менің логарифмдік санау жүйесін (LNS) тәжірибелік енгізуімнің қысқаша мазмұны. 1. PyTorch жүйесіндегі негізгі LNS тұжырымдамасы және қиындықтары LNS жүйесінде сандар көбейту мен бөлуді қосу мен азайтуға түрлендіретін логарифмдер түрінде берілген. Дегенмен, мұны PyTorch көмегімен жүзеге асыру нақты қиындықтарды тудырады, өйткені PyTorch тензорлары өзгермелі нүкте көріністерін іштей пайдаланады. Бұл бірнеше талаптарды тудырады: Есептеу кезінде логарифмдік көріністі сақтаңыз. Сандық тұрақтылықты қамтамасыз ету. Түрлендірулерді мұқият өңдеңіз. Екі құрамдас арқылы ішкі көріністі басқарыңыз: : логарифмдік мән. x : белгі биті (0 немесе 1). s 2. Ішкі өкілдік және конверсия Бірінші қадам өзгермелі нүкте сандарын олардың LNS ішкі көрінісіне түрлендіру болып табылады. 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 Ол өзгермелі нүктелі дөңгелектеу қателерінсіз нақты LNS ішкі көрінісін сақтайды. Логарифмдік мәнді де, таңба битін де бір бүтін санға қосады. Қажетсіз өзгермелі нүкте әрекеттерінің LNS көрінісін бұзуына жол бермейді. 3. Негізгі арифметикалық амалдар а) Көбейту def lns_mul_internal(x, y): return x + y LNS ішіндегі көбейту қосуға айналады: Егер және болса, онда . a = log(x) b = log(y) log(x×y) = log(x) + log(y) б) Бөлу def lns_div_internal(x, y): return x - y Бөлу азайтуға айналады: . log(x/y) = log(x) - log(y) в) Қосу 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 Қосу күрделірек және сандық жағынан сезімтал, себебі: Ол көрсеткіштік және логарифмдік амалдарды қамтиды. Тікелей өзгермелі нүктені енгізу толып кетуге/толып кетуге әкелуі мүмкін. Теңдеуді пайдаланады: . log(x + y) = log(max(x,y)) + log(1 + exp(log(min(x,y)) - log(max(x,y)))) Жақсырақ сандық тұрақтылық үшін тікелей орнына пайдаланады. log(1 + x) log1p 4. Қауіпсіздік және түрлендіруді басқару түрі def internal_to_float(internal_data): for value in internal_data: x = value // 2 # Integer division s = value % 2 # Integer modulo Түрлендіру құбыры нақты бөлуді сақтайды: Float → LNS ішкі көрінісінен түрлендіру (бүтін сандар). Бүтін арифметика арқылы LNS операцияларын орындаңыз. Қажет болғанда ғана қалқымалы күйге қайта түрлендіру. # 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. Негізгі артықшылықтар мен шектеулер Артықшылықтары . Көбейту және бөлу қосу және азайтуға оңайлатылған Бекітілген нүктелік арифметикасы бар . кең динамикалық диапазон Белгілі бір қолданбалар үшін . тиімдірек Шектеулер амалдар. Қосу және алу күрделірек Жылжымалы нүкте мен LNS арасындағы . конверсиялық үстеме шығындар Нөлдік және теріс сандар үшін . арнайы өңдеуді қажет етеді түрді мұқият басқаруды қажет етеді. PyTorch тензорының үйлесімділігі 6. Оңтайландыру мүмкіндіктері Өнімділікті жақсарту үшін келесі әрекеттерді орындауға болады: LNS операциялары үшін іске қосыңыз. теңшелетін PyTorch autograd функциясын LNS қолдайтын жасаңыз. теңшелетін тензор түрін GPU жүйесінде тиімді LNS операциялары үшін пайдаланыңыз. CUDA ядроларын Ағымдағы енгізу практикалық айырбастарды жасайды: Максималды өнімділікке қарағанда басымдық береді. айқындылық пен тұрақтылыққа LNS дәлдігін сақтай отырып, PyTorch пайдаланады. бар тензорлық инфрақұрылымын Түрді мұқият басқару арқылы сақтайды. сандық тұрақтылықты азайтады. Көріністер арасындағы түрлендірулерді 7. Деректер ағынының мысалы Келесі қадамдар және мысал мәндерін қолданып толық құбырды көрсетеді: [2.0, 3.0] [-1.0, 0.0] Кіріс қалқымалы мәндерін LNS ішкі көрінісіне түрлендіру. LNS мәндерін сақтау үшін бүтін тензорларды жасаңыз. LNS доменінде арифметикалық амалдарды орындаңыз. Нәтижелерді өзгермелі нүктеге қайта түрлендіру. Әрі қарай өңдеу үшін соңғы PyTorch тензорларын жасаңыз. Бұл іске асыру сандық тұрақтылық пен дәлдікті сақтай отырып, PyTorch қалқымалы нүктелі тензор жүйесі мен LNS арифметикасының арасындағы алшақтықты сәтті өтейді. FP және LNS көмегімен MNIST Digit деректер жинағында толық қосылған MLP-ді үйрету Экспериментті орнату Мен MNIST деректер жинағында FP және LNS өкілдіктерін пайдалана отырып, толық қосылған MLP оқыттым. Модельдің архитектурасы қарапайым болды: 784 нейрон (28x28 тегістелген кескіндер) Кіріс қабаты: 256 және 128 нейрондары бар екі қабат, ReLU активациялары Жасырын қабаттар: 10 нейрон (әр сан үшін бір, softmax көмегімен) Шығару деңгейі: кросс-энтропия Жоғалту функциясы: Адам Оңтайландырушы: LNS енгізу үшін маған әдеттегі PyTorch жұмыс үрдісінен шығуға тура келді. PyTorch қолдайтын FP-ден айырмашылығы, PyTorch кірістірілген LNS операцияларын қамтамасыз етпейді. Мен логарифмдік сандарды ұсыну мен арифметиканы жүзеге асыратын, нейрондық желілерде LNS пайдалануға мүмкіндік беретін деп аталатын GitHub жобасын таптым. xlns PyTorch ішіндегі Floating-Point MLP Біз PyTorch көмегімен стандартты FP негізінде толық қосылған MLP енгізуден бастаймыз: 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) Бұл енгізу көбейту мен қосулар FP арифметикасымен өңделетін кәдімгі терең оқыту құбырынан кейін жүреді. Мұнда MNIST деректер жинағы үшін көп деңгейлі перцептронды (MLP) осы PyTorch іске асырудың егжей-тегжейлі шолуы берілген. Модельдік архитектура (MLP сыныбы): 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) Алға өту: 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 Жаттығуды орнату: 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] ]) Негізгі компоненттер: Құрылғыны таңдау арқылы GPU қолдауы Жаттығуды жақсарту үшін деректерді қалыпқа келтіру Конфигурацияланатын гиперпараметрлер Деректер жиынын басқару: 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 деректер жинағын жүктеп алады Деректерді оқыту (80%) және тексеру (20%) жиындарына бөледі Жаттығу циклі: 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 Классикалық жаттығу процедурасы: Нөлдік градиенттер Алға өту Шығындарды есептеу Артқа өту Салмақ жаңартулары Тексеру: 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() Негізгі мүмкіндіктер: Модель бағалау режиміне орнатылды Градиентті есептеу қажет емес Дәлдік есептеу Көрнекілігі: def show_predictions(model, data_loader, device, num_images=6): model.eval() plt.figure(figsize=(12, 8)) # Display predictions vs actual labels Тексеру жиынынан үлгі болжамдарын көрсетеді Сапалық бағалау үшін пайдалы Өнімділікті қадағалау: # 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') Жаттығу және тексеру дәлдігін қадағалайды Оқу қисықтарының сызбасын салады Жаттығу уақытын өлшейді Бұл LNS негізіндегі енгізулермен салыстыру үшін берік негіз береді, өйткені ол дәстүрлі өзгермелі нүкте арифметикасы арқылы терең оқыту құбырының барлық стандартты құрамдастарын жүзеге асырады. Логарифмдік санау жүйесі (LNS) MLP LNS үшін біз кітапханасын пайдалануымыз керек. FP-ден айырмашылығы, LNS көбейтуді қажет ететін операцияларды логарифмдік домендегі қосумен ауыстырады. Дегенмен, PyTorch мұны жергілікті түрде қолдамайды, сондықтан қажет болған жағдайда LNS операцияларын қолмен қолдануымыз керек. xlns 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) Мен сізге MNIST цифрлық классификациясы үшін логарифмдік санау жүйесін (LNS) көп деңгейлі перцептронды (MLP) жүзеге асыратын осы код арқылы таныстырамын. Оны негізгі бөлімдерге бөлуге рұқсат етіңіз: Орнату және импорттау: Код логарифмдік санау жүйесінің операциялары үшін кітапханасын пайдаланады xlns Ол әртүрлі дәлдік пен өнімділік үшін бірнеше LNS нұсқаларын (xlnsnp, xlnsnpv, xlnsud, т.б.) ұсынады. MNIST деректер жинағы Keras арқылы жүктеледі Негізгі функциялар: 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 Бұл LNS операцияларына бейімделген сандық тұрақты softmax іске асыру. Желінің архитектурасы: Кіріс қабаты: 784 нейрон (28x28 тегістелген MNIST кескіндері) + 1 қиғаштық = 785 Жасырын қабат: 100 нейрон + 1 қиғаштық = 101 Шығыс деңгейі: 10 нейрон (әр санға бір) Салмақты инициализациялау: Салмақ файлдан («weightin.npz») жүктеледі немесе кездейсоқ түрде инициализацияланады Кездейсоқ салмақтар орташа=0, std=0,1 болатын қалыпты үлестіруді пайдаланады Әртүрлі LNS нұсқалары әртүрлі инициализация әдістерін қажет етеді (xlnsnp, xlnsnpv, т.б.) Жаттығу циклі: 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 Тренингтің негізгі аспектілері: Ағып кеткен ReLU белсендіруін пайдаланады (leaking_coeff арқылы басқарылады) Стандартты кері таралуды жүзеге асырады, бірақ LNS операцияларымен L2 реттеуді қамтиды (лямбда параметрі) "lr" оқу жылдамдығымен градиентті төмендету арқылы салмақтарды жаңартады Бағалау: Жаттығудың да, валидацияның дәлдігін де қадағалайды Дәуірлер бойынша дәлдікті көрсететін оқу қисықтарының сызбалары Сынақ кескіндеріндегі үлгі болжамдарын көрсетеді Гиперпараметрлер: 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' } Шағын топтаманың градиент түсуін пайдаланады (әдепкі пакет өлшемі = 1) Валидация жиынын бөлу арқылы ерте тоқтатуды жүзеге асырады Leaky ReLU коэффициенті 0,0078125 мәніне орнатылған Көрнекілігі: Жаттығу және тексеру дәлдігін көрсететін сюжеттер жасайды Болжамдар мен шынайы белгілермен үлгі сынақ кескіндерін көрсетеді Дәлдік сызбасын "genericaccuracy.png" ретінде сақтайды Мұндағы негізгі жаңалық - LNS арифметикасын қолдану, ол көбейтуді журнал доменіндегі толықтырулармен ауыстырады, бұл белгілі бір аппараттық іске асыру үшін жақсырақ есептеу тиімділігін ұсынады. Код әртүрлі дәлдік-өнімділік алмасуларына мүмкіндік беретін бірнеше LNS нұсқаларын қолдайды. Негізгі өнімділікті салыстыру Қалқымалы нүкте үлгісінің өнімділігі 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. Логарифмдік санау жүйесінің моделінің өнімділігі 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. FP және LNS: негізгі салыстырулар Аспект Қалқымалы нүкте (FP) Логарифмдік санау жүйесі (LNS) Жаттығу уақыты 57,76 с 0,35 с Пойыздың дәлдігі 91,60% 96,00% Val дәлдігі 91,62% 68,00% Дәлдік Жоғары Төменгі (жақындау қателері) Жад тиімділігі Жоғарырақ пайдалану Жадтың төменгі ізі Көбейтуді өңдеу Туынды көбейту Қосуға негізделген жеңілдетулер Қорытынды мен арасындағы айырмашылықтар нейрондық желілерге арналған аппараттық-бағдарламалық қамтамасыз етудің бірлескен дизайнындағы қызықты мысалды ұсынады. LNS белгілі бір салаларда айтарлықтай артықшылықтар ұсынады: Логарифмдік санау жүйесі (LNS) қалқымалы нүкте (FP) арифметикасының Жаттығу жылдамдығы Журнал доменінде көбейтуді қосумен ауыстырады Күрделі амалдарды қарапайым арифметикаға азайтады Нейрондық желілерде матрицаны көбейту үшін әсіресе тиімді Кейбір енгізулерде қол жеткізуге болады 2–3 есе жылдамдыққа Жад артықшылықтары Әдетте сандарды көрсету үшін қажет азырақ бит алады Салмақтарды және белсендірулерді тиімдірек қыса қойылатын талаптарды азайтады Жад өткізу қабілетіне Жадқа қол жеткізу үшін аз қуат тұтыну Дегенмен, маңызды: дәлдік бойынша қиындықтар Кішігірім мәндерді жинақтау кезінде дәлдікті жоғалту Нөлге жақын сандарды көрсетудің қиындығы Градиенттік есептеулердегі потенциалдық тұрақсыздық қажет етуі мүмкін Гиперпараметрді мұқият реттеуді Болашақ бағыттары Бірнеше перспективалы тәсілдер LNS қолдану мүмкіндігін арттыруы мүмкін: 1. Қабатқа арналған арифметика пайдаланыңыз (соңғы жіктеу сияқты) Сезімтал қабаттар үшін FP қолданыңыз LNS есептеуді қажет ететін жасырын қабаттарда Сандық талаптарға негізделген динамикалық ауысу 2. Дәлдікке бейімделген есептеулер Тұрақтылық үшін FP жаттығуын бастаңыз Салмақтар жақындаған сайын LNS-ге біртіндеп ауысыңыз Критикалық жолдарды жоғары дәлдікте ұстаңыз 3. Аппараттық құралдардың бірлескен дизайны FP және LNS бірліктері бар теңшелетін үдеткіштер Арифметикалық түрлер арасындағы ақылды жоспарлау Әрбір пішім үшін арнайы жад иерархиялары 4. Алгоритмдік инновациялар LNS үшін оңтайландырылған жаңа белсендіру функциялары Тұрақтылықты сақтайтын модификацияланған оңтайландыру алгоритмдері Гибридті сандарды көрсету Потенциалды PyTorch қолдауы LNS-ті терең оқыту құрылымдарына біріктіру үшін мыналарды зерттеуге болады: 1. Теңшелетін Autograd функциялары орындаңыз LNS операцияларын теңшелетін автоградтық функциялар ретінде сақтаңыз Журнал доменінде градиентті есептеуді Жеделдету үшін қамтамасыз етіңіз тиімді CUDA ядроларын 2. Сан түрінің кеңейтімдері қосыңыз Жергілікті LNS тензор түрлерін Журнал доменінде (*+, -, ) орындаңыз негізгі операцияларды , / Қалқымалы нүктеге/қайтадан қамтамасыз етіңіз түрлендіру утилиталарын 3. Қабат модификациялары жасау (Linear, Conv2d) Жалпы қабаттардың LNS нұсқаларын LNS есептеуі үшін оңтайландыру кері өтулерді қолдау Аралас дәлдік жаттығуларын Терең білім беру қауымдастығы бұл мүмкіндіктерді мүмкіндік беретін негізгі құрылымдарға біріктіруден үлкен пайда көре алады. тиімдірек, төмен қуатты және жоғары жылдамдықты нейрондық желілерге Сандық дәлдік пен есептеу тиімділігі арасындағы тепе-теңдік туралы ойларыңыз қандай? LNS әсіресе пайдалы болуы мүмкін нақты пайдалану жағдайларын кездестірдіңіз бе? Бұл туралы өз ойларыңызды айтыңыз. Анықтамалар [1] G. Alsuhli, et al., “Number Systems for Deep Neural Network Architectures: A Survey,” , 2023 ж. arXiv:2307.05035 [2] М.Арнольд, Э.Честер және т.б., «Тек жуық кестесіз LNS ALU көмегімен нейрондық желілерді оқыту». , 2020, 69–72 беттер. Қолданбаларға арналған арнайы жүйелер, архитектуралар және процессорлар бойынша 31-ші халықаралық конференция, IEEE DOI [3] О. Кошелева, т.б., «Логарифмдік санау жүйесі AI есептеулері үшін оңтайлы: эмпирикалық табыстың теориялық түсіндірмесі», қағаз [4] Д.Мияшита және т.б., «Логарифмдік деректерді ұсынуды пайдаланатын конволюциондық нейрондық желілер», , наурыз 2016 ж. arXiv:1603.01025 [5] J. Zhao et al., “LNS-Madam: Low-Precision Training in Logarifmic Number System in Multiplicative Weight Update,” , том. 71, жоқ. 12, 3179–3190 беттер, 2022 ж. желтоқсан. IEEE Transactions on Computers DOI