Ewgeniy

Untitled

Jun 11th, 2026 (edited)
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.96 KB | None | 0 0
  1. math.randomseed(os.time())
  2.  
  3. -- Функции ANSI ESC для управления терминалом
  4. local function clear()
  5.   io.write("\27[2J")     -- очистить весь экран
  6.   io.write("\27[H")      -- переместить курсор в левый верхний угол
  7. end
  8.  
  9. local function gotoXY(x, y)
  10.   io.write(string.format("\27[%d;%dH", y, x))
  11. end
  12.  
  13. local function clearLine()
  14.   io.write("\27[2K") -- очистить текущую строку
  15. end
  16.  
  17. -- Гиперпараметры
  18. local N = 53       -- размер словаря чисел (0..52)
  19. local DIM = 16
  20. local HIDDEN = 32
  21. local LR = 0.01
  22. local STEPS = 30000
  23.  
  24. -- Создаем тензор случайных чисел
  25. local function randomMatrix(rows, cols)
  26.   local m = {}
  27.   for i=1, rows do
  28.     m[i] = {}
  29.     for j=1, cols do
  30.       m[i][j] = (math.random() - 0.5) * 2
  31.     end
  32.   end
  33.   return m
  34. end
  35.  
  36. -- Ядро нейросети (все как раньше) —
  37. -- ниже функции dot, relu, softmax, forward, backward, trainStep, predict —
  38. -- для краткости не дублирую весь код здесь, используйте ваш.
  39. -- Важно, что их интерфейс остаётся прежним.
  40.  
  41. -- Для полноты добавляю минимальный вариант (копируйте в ваш скрипт):
  42.  
  43. local function zeros(n)
  44.   local t = {}
  45.   for i=1,n do t[i]=0 end
  46.   return t
  47. end
  48.  
  49. local function dot(a,b)
  50.   local s = 0
  51.   for i=1,#a do s = s + a[i]*b[i] end
  52.   return s
  53. end
  54.  
  55. local function relu(x)
  56.   local r = {}
  57.   for i=1,#x do r[i] = math.max(0, x[i]) end
  58.   return r
  59. end
  60.  
  61. local function relu_derivative(x)
  62.   local r = {}
  63.   for i=1,#x do r[i] = x[i] > 0 and 1 or 0 end
  64.   return r
  65. end
  66.  
  67. local function softmax(x)
  68.   local maxv = math.max(table.unpack(x))
  69.   local exps = {}
  70.   local sum = 0
  71.   for i=1,#x do
  72.     exps[i] = math.exp(x[i] - maxv)
  73.     sum = sum + exps[i]
  74.   end
  75.   local r = {}
  76.   for i=1,#x do r[i] = exps[i]/sum end
  77.   return r
  78. end
  79.  
  80. local function crossEntropyLoss(probs, target_idx)
  81.   return -math.log(probs[target_idx] or 1e-15)
  82. end
  83.  
  84. local function gradientCrossEntropy(probs, target_idx)
  85.   local grad = {}
  86.   for i=1,#probs do grad[i] = probs[i] end
  87.   grad[target_idx] = grad[target_idx] - 1
  88.   return grad
  89. end
  90.  
  91. local function concat(a,b)
  92.   local r = {}
  93.   for i=1,#a do r[#r+1] = a[i] end
  94.   for i=1,#b do r[#r+1] = b[i] end
  95.   return r
  96. end
  97.  
  98. -- Инициализация весов и эмбеддингов
  99. local emb = randomMatrix(N, DIM)
  100. local w1 = randomMatrix(2*DIM, HIDDEN)
  101. local b1 = {}
  102. for i=1,HIDDEN do b1[i] = 0 end
  103. local w2 = randomMatrix(HIDDEN, N)
  104. local b2 = {}
  105. for i=1,N do b2[i] = 0 end
  106.  
  107. -- forward, backward, trainStep, predict (используйте ваши реализации из предыдущих шагов)
  108.  
  109. local function forward(a_idx, b_idx)
  110.   local emb_a = emb[a_idx + 1]
  111.   local emb_b = emb[b_idx + 1]
  112.   local input = concat(emb_a, emb_b)
  113.  
  114.   local h_raw = {}
  115.   for i=1,HIDDEN do
  116.     local sum = b1[i]
  117.     for j=1, 2*DIM do
  118.       sum = sum + w1[j][i] * input[j]
  119.     end
  120.     h_raw[i] = sum
  121.   end
  122.   local h = relu(h_raw)
  123.  
  124.   local out_raw = {}
  125.   for i=1,N do
  126.     local sum = b2[i]
  127.     for j=1,HIDDEN do
  128.       sum = sum + w2[j][i] * h[j]
  129.     end
  130.     out_raw[i] = sum
  131.   end
  132.   local out = softmax(out_raw)
  133.  
  134.   return {
  135.     input = input,
  136.     emb_a = emb_a,
  137.     emb_b = emb_b,
  138.     h_raw = h_raw,
  139.     h = h,
  140.     out_raw = out_raw,
  141.     out = out
  142.   }
  143. end
  144.  
  145. local function backward(cache, a_idx, b_idx, target_idx)
  146.   -- аналогично вашему коду, обновляет веса
  147.   local out = cache.out
  148.   local h = cache.h
  149.   local h_raw = cache.h_raw
  150.   local input = cache.input
  151.  
  152.   local grad_out = gradientCrossEntropy(out, target_idx + 1)
  153.  
  154.   local grad_w2 = {}
  155.   for j=1,HIDDEN do
  156.     grad_w2[j] = {}
  157.     for i=1,N do
  158.       grad_w2[j][i] = grad_out[i] * h[j]
  159.     end
  160.   end
  161.   local grad_b2 = grad_out
  162.  
  163.   local grad_h = zeros(HIDDEN)
  164.   for j=1,HIDDEN do
  165.     local s = 0
  166.     for i=1,N do
  167.       s = s + grad_out[i] * w2[j][i]
  168.     end
  169.     grad_h[j] = s
  170.   end
  171.  
  172.   local relu_der = relu_derivative(h_raw)
  173.   for j=1,HIDDEN do
  174.     grad_h[j] = grad_h[j] * relu_der[j]
  175.   end
  176.  
  177.   local grad_w1 = {}
  178.   for i=1, 2*DIM do
  179.     grad_w1[i] = {}
  180.     for j=1,HIDDEN do
  181.       grad_w1[i][j] = grad_h[j] * input[i]
  182.     end
  183.   end
  184.   local grad_b1 = grad_h
  185.  
  186.   local grad_input = zeros(2*DIM)
  187.   for i=1, 2*DIM do
  188.     local s = 0
  189.     for j=1,HIDDEN do
  190.       s = s + grad_h[j] * w1[i][j]
  191.     end
  192.     grad_input[i] = s
  193.   end
  194.  
  195.   for i=1, 2*DIM do
  196.     for j=1,HIDDEN do
  197.       w1[i][j] = w1[i][j] - LR * grad_w1[i][j]
  198.     end
  199.   end
  200.   for j=1,HIDDEN do
  201.     b1[j] = b1[j] - LR * grad_b1[j]
  202.   end
  203.  
  204.   for j=1,HIDDEN do
  205.     for i=1,N do
  206.       w2[j][i] = w2[j][i] - LR * grad_w2[j][i]
  207.     end
  208.   end
  209.   for i=1,N do
  210.     b2[i] = b2[i] - LR * grad_b2[i]
  211.   end
  212.  
  213.   for i=1,DIM do
  214.     emb[a_idx + 1][i] = emb[a_idx + 1][i] - LR * grad_input[i]
  215.     emb[b_idx + 1][i] = emb[b_idx + 1][i] - LR * grad_input[DIM + i]
  216.   end
  217. end
  218.  
  219. local function trainStep(a_idx, b_idx)
  220.   local cache = forward(a_idx, b_idx)
  221.   local target = (a_idx + b_idx) % N
  222.   local loss = crossEntropyLoss(cache.out, target + 1)
  223.   backward(cache, a_idx, b_idx, target)
  224.   return loss
  225. end
  226.  
  227. local function predict(a_idx, b_idx)
  228.   local cache = forward(a_idx, b_idx)
  229.   local out = cache.out
  230.   local max_prob = -1
  231.   local max_idx = -1
  232.   for i=1,#out do
  233.     if out[i] > max_prob then
  234.       max_prob = out[i]
  235.       max_idx = i-1
  236.     end
  237.   end
  238.   return max_idx, max_prob
  239. end
  240.  
  241. -- Визуализация эмбеддингов и график точности
  242.  
  243. local function meanCenter(matrix)
  244.   local n = #matrix
  245.   local dim = #matrix[1]
  246.   local means = {}
  247.   for d=1, dim do
  248.     means[d] = 0
  249.     for i=1, n do means[d] = means[d] + matrix[i][d] end
  250.     means[d] = means[d] / n
  251.   end
  252.   local centered = {}
  253.   for i=1, n do
  254.     centered[i] = {}
  255.     for d=1, dim do
  256.       centered[i][d] = matrix[i][d] - means[d]
  257.     end
  258.   end
  259.   return centered
  260. end
  261.  
  262. local function project2D(matrix)
  263.   local centered = meanCenter(matrix)
  264.   local points = {}
  265.   for i=1, #centered do
  266.     points[i] = {x = centered[i][1], y = centered[i][2]}
  267.   end
  268.   return points
  269. end
  270.  
  271. local function drawPoints(points)
  272.   local width, height = 60, 20
  273.   local xmin, xmax, ymin, ymax = points[1].x, points[1].x, points[1].y, points[1].y
  274.   for _, p in ipairs(points) do
  275.     if p.x < xmin then xmin = p.x end
  276.     if p.x > xmax then xmax = p.x end
  277.     if p.y < ymin then ymin = p.y end
  278.     if p.y > ymax then ymax = p.y end
  279.   end
  280.   local scaleX = (xmax - xmin) > 0 and (width-1)/(xmax - xmin) or 1
  281.   local scaleY = (ymax - ymin) > 0 and (height-1)/(ymax - ymin) or 1
  282.   local grid = {}
  283.   for y=1,height do
  284.     grid[y] = {}
  285.     for x=1,width do
  286.       grid[y][x] = " "
  287.     end
  288.   end
  289.   for _, p in ipairs(points) do
  290.     local x = math.floor((p.x - xmin)*scaleX) + 1
  291.     local y = height - math.floor((p.y - ymin)*scaleY)
  292.     if x >= 1 and x <= width and y >= 1 and y <= height then
  293.       grid[y][x] = "*"
  294.     end
  295.   end
  296.  
  297.   -- Очистка области и вывод
  298.   gotoXY(1, 5)
  299.   for y=1,height do
  300.     clearLine()
  301.     io.write(table.concat(grid[y]).."\n")
  302.   end
  303. end
  304.  
  305. local accHistory = {}
  306.  
  307. local function drawAccuracy()
  308.   local width, height = 60, 10
  309.   local len = #accHistory
  310.   local start = len > width and (len - width + 1) or 1
  311.   local slice = {}
  312.   for i=start,len do
  313.     slice[#slice+1] = accHistory[i]
  314.   end
  315.   local grid = {}
  316.   for y=1,height do
  317.     grid[y] = {}
  318.     for x=1,#slice do
  319.       grid[y][x] = " "
  320.     end
  321.   end
  322.   for x=1,#slice do
  323.     local value = slice[x]
  324.     local barHeight = math.floor(value * height)
  325.     for y=height, height - barHeight + 1, -1 do
  326.       grid[y][x] = "#"
  327.     end
  328.   end
  329.  
  330.   gotoXY(1, 26)
  331.   for y=1,height do
  332.     clearLine()
  333.     io.write(table.concat(grid[y]).."\n")
  334.   end
  335.   gotoXY(1, 36)
  336.   clearLine()
  337.   io.write(string.format("Точность сейчас: %.2f%%\n", (slice[#slice] or 0) * 100))
  338. end
  339.  
  340. local function printProgress(step, maxSteps, loss, accuracy)
  341.   gotoXY(1,1)
  342.   clearLine()
  343.   local barWidth = 30
  344.   local progress = math.floor((step / maxSteps) * barWidth)
  345.   local bar = "[" .. string.rep("=", progress) .. string.rep(" ", barWidth - progress) .. "]"
  346.   io.write(string.format("Шаг %6d/%d %s  Потеря: %.4f  Точность: %.2f%%\n", step, maxSteps, bar, loss, accuracy * 100))
  347.   io.flush()
  348. end
  349.  
  350. local function computeAccuracy(samples)
  351.   local correct = 0
  352.   for _, sample in ipairs(samples) do
  353.     local a,b,target = sample[1], sample[2], sample[3]
  354.     local pred,_ = predict(a, b)
  355.     if pred == target then correct = correct + 1 end
  356.   end
  357.   return correct / #samples
  358. end
  359.  
  360. local function generateValidationSet(size)
  361.   local valSet = {}
  362.   for i=1,size do
  363.     local a, b = math.random(0, N-1), math.random(0, N-1)
  364.     table.insert(valSet, {a,b,(a+b)%N})
  365.   end
  366.   return valSet
  367. end
  368.  
  369. -- Очистить экран перед запуском
  370. clear()
  371.  
  372. print("Старт обучения...")
  373. local valSet = generateValidationSet(500)
  374. for step=1, STEPS do
  375.   local a_idx = math.random(0, N-1)
  376.   local b_idx = math.random(0, N-1)
  377.   local loss = trainStep(a_idx, b_idx)
  378.  
  379.   if step % 100 == 0 then
  380.     local acc = computeAccuracy(valSet)
  381.     printProgress(step, STEPS, loss, acc)
  382.     os.sleep(0.01)
  383.   end
  384.  
  385.   if step % 1000 == 0 then
  386.     accHistory[#accHistory + 1] = computeAccuracy(valSet)
  387.     local points2D = project2D(emb)
  388.     drawPoints(points2D)
  389.     drawAccuracy()
  390.     os.sleep(0.05)
  391.   end
  392. end
  393.  
  394. gotoXY(1, 40)
  395. print("\nОбучение завершено.\nПримеры предсказаний после обучения:")
  396. for a=0,10 do
  397.   for b=0,10 do
  398.     local pred, prob = predict(a,b)
  399.     local target = (a+b) % N
  400.     local res = (pred == target) and "OK" or "ERR"
  401.     io.write(string.format("%2d+%2d=%2d(%s), p=%.2f  ", a,b,pred,res,prob))
  402.   end
  403.   print()
  404. end
  405.  
Advertisement
Add Comment
Please, Sign In to add comment