CodeLab
145 subscribers
538 photos
20 videos
159 links
Говорим просто о сложном

Обсуждение, новости, материал и сплетни — все здесь https://t.me/CodeLabMLChat
Download Telegram
👀Самое интересное — это аниме тянка и 18+ режимы для голосового общения. Прикрепил мысли o3, мб интересно будет 🤷. Как по мне, Маск сделал очень...

ДОЧИТЫВАЕМ В НАШЕМ ЧАТИКЕ
Please open Telegram to view this post
VIEW IN TELEGRAM
511
Новый пост после 140 подписичников будет
1111
👏
Please open Telegram to view this post
VIEW IN TELEGRAM
1111
2111
👨‍💻 Друзья, пост про библиотеки для ML уже в нашем чате ⬇️

СМОТРИМ ЗДЕСЬ
Please open Telegram to view this post
VIEW IN TELEGRAM
2111
This media is not supported in your browser
VIEW IN TELEGRAM
Снова роботы бесоёбят
2211
👀 Всем ку, подписичники прибавились, а значит пора выложить пост. Я вдруг понял, что задачки с бинарной классификацией закончились, но поводов расстраиваться нет, ведь мы переходим к градиентному спуску.

Здесь
, здесь, здесь и здесь мы уже рассмотрели эту тему (и весьма неплохо), но теперь будем углубляться и решать задачки.

🔤🌹🔤🔤🔤🔤🔤🌷 🔤🔤🔤🔤🔤🔤🌷

🔵Я все же настаиваю на том, чтобы вы изучили материал, что я дал выше ⬆️ —там объяснение формул и сама база. Сейчас держите краткое резюме для тех, кто забыл:

‼️ Градиентный спуск — это алгоритм оптимизации, который итеративно изменяет внутренние параметры модели (веса, смещение).

Для чего ему их изменять? — Для минимизации функции потерь.

Что такое функция потерь? — По сути это оценка модели (разница между предсказаниями модели и реальными целевыми значениями).

‼️ Итак, получается, что Градиентный спуск это алгоритм, который меняет параметры чтобы уменьшить разницу между предсказаниями и истинными значениями.


👨‍💻Базу вспомнили, теперь про сам алгоритм:

Как работает?

1⃣ Берем начальное значение параметра

2⃣ Считаем градиент (первая производная функции)

3⃣ Делаем шаг в сторону противоположную градиенту, чтобы уменьшить значение функции f(x)

4⃣ Повторяем, пока не дойдём до минимума

⚙️ Итак, разберем простой пример:

🟰 x = x - η * f'(x) 🟰— вот формула градиентного спуска, теперь, представим, что у нас есть такая простенькая функция:

🟰 f(x) = x² 🟰

🟰 f'(x) = 2x 🟰 — теперь берем производную

‼️ Итак, допустим, x = 4, тогда f'(x) = 8 (умножили на 2) ➡️ значит, функция возрастает, надо идти влево по графику (пример в комментах)

Вот тут нам и нужна формула:

🟰 f'(4) = 2 * 4 = 8 🟰 ➡️4 - 0.1 * 8 = 4 - 0.8 = 3.2 — это новый x (старый был 4). Тоже самое можно проделывать до того момента, пока не найдем минимум функции

‼️ А если x = -3? Тогда f'(x) = -6 ➡️ функция возрастает влево, и чтобы её уменьшить, надо идти вправо

Это правило работает везде — в отрицательной и положительной области

🟢Градиент подсказывает, в какую сторону растёт функция

🟢Мы идём в противоположную сторону, чтобы уменьшить значение функции


👨‍💻Скоро продолжим
Please open Telegram to view this post
VIEW IN TELEGRAM
3211
👨‍💻Всем сап! В прошлом посте разбирали градиентный спуск, теперь самое интересное ➡️ КОД (пост оказался сложнее, чем я думал, приходится сидеть и думать 🤔🤔)

🔵Функцию берем вот эту 🟰 f(x) = x² - 5x + 5 🟰

🔵Теперь производная 🟰 f'(x) = 2x - 5 🟰


0⃣ Библиотеки:

import time
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np


1⃣ Функции, которые я прописал выше (просто переписываем):

def f(x): # Функция f(x)
return x * x - 5 * x + 5

def df(x): # Проивзодная функции f(x)
return 2 * x - 5


2⃣ Теперь вводим некоторые переменные:


🔵(Число итераций (N); — проще говоря, сколько шагов градиентного спуска мы делаем

🔵Начальное значение (xx); — стартовая точка, c нее мы начнем ползти по антиградиенту (это вниз если что, градиент указывает направление наискорейшего роста функции, антиградиент — направление наискорейшего убывания)

🔵Шаг сходимости (lmd) — проще говоря, это learning rate (длина шага).

🟰 xₖ₊₁ = xₖ - λf'(xₖ) 🟰 — вот по такой формуле делает шаг градиентный спуск. Если мы подставим 🟰 f'(x) = 2x - 5 🟰то получим 2.5

‼️ Кстати, эту формулу также записывают как 🟰 xₖ₊₁ = xₖ - λ∇ f'xₖ) 🟰Разница лишь в том, что в первом случае f'(x) — это обычная производная по одной переменной, а в другом — f(x) — вектор частных производных (как итог, формула одна и та же)

N = 20 
xx = 0
lmd = 0.1


👨‍💻 Итак, мы хотим найти x, где функция потерь f(x) минимальная, формулу шага градиентного спуска мы уже разобрали, хотя, можно еще один момент разобрать:

∇f(x) — стрелка вверх (т.е куда быстрее всего растет f) — это направление наискорейшего роста

-∇f(x)направление наискорейшего убывания (в комментах материал)

Можем кстати подставить в нашу формулу пример 🟰 xₖ₊₁ = xₖ - λf'(xₖ) 🟰 ➡️ получаем 🟰 xₖ₊₁ = xₖ - λ * (2x - 5)) 🟰 ➡️ 🟰(1 - 2λ) * xₖ + 5λ🟰 — это правило обновления итераций (наша функция)

‼️САМА СУТЬ — НАЙТИ ТОЧКУ, ГДЕ ДВИЖЕНИЕ ПРЕКРАЩАЕТСЯ (итерации прекращаются) — еще проще, найти глобальный минимум.


🔵А так, я нашел, что глобальный минимум можно найти кучей способов, самый простой — вершина параболы: напомню, у нас функция 🟰 f(x) = x² - 5x + 5 🟰

🔵 x (вершина параболы) = -b / 2a = 2.5 (просто подставляем наши значения, вот вам и глобальный минимум)

Совсем скоро продолжим 💤
Please open Telegram to view this post
VIEW IN TELEGRAM
2111
👨‍💻 Итак, продолжаем:

⚙️Наш код на данный момент выглядит так:

import numpy as np
import matplotlib.pyplot as plt

def f(x): # f(x) = x^2 - 5x + 5 # парабола
return x*x - 5*x + 5

def df(x): # f'(x) = 2x - 5 # наклон графика в точке x
return 2*x - 5

N = 20 # число итераций
x = 0.0 # стартовая точка x0
lr = 0.1 # шаг обучения (λ)


🔵N — это количество обновлений

🔵lr — это длина шага

Возможно, вы заметили, что я убрал библиотеку time, ее я заменил привычной нам matplotlib, суть не поменялась (все это не влияет на наш алгоритм, исключительно для плавной анимации спуска)

3⃣ Создаем массив точек из 400 точек, по этим точкам и будем рисовать кривую f(x)

xs = np.linspace(-1, 5, 400)


4⃣ Включаем интерактивный режим Matplotlib (для анимации в цикле). ‼️ Важно, анимация у меня в колабе не отобразилась, мб это особенность блокнотов, в VS все нормально.

🔵Что касаемо остальных строк, fig, ax = plt.subplots() — будет создавать окошко Figure и систему координат Axes (сетка, подписи и две оси — x, y)

🔵ax.grid(True) — включает сетку на осях

🔵ax.plot(xs, f(xs), label="f(x)") — рисует линию функции f(x) по сетке xs. ‼️ В общем, мы создавали массив из 400 точек, так вот когда мы вызываем f(xs), Numpy поэлементно будет считать y = f(x) для каждого из этих 400 точек

🔵pt = ax.scatter([x], [f(x)], c='red', s=50) рисует красную точку в текущем положении (x, f(x)) для визуализации текущего x на каждом шаге спуска.

🔵ax.set_xlim(xs.min(), xs.max()) фиксирует границы оси X от минимума до максимума нашей сетки (таким образом, будем отображаться ровно тот интервал, где мы нарисовали кривую + масштаб во время анимации не будет прыгать)

🔵ax.set_ylim(f(xs).min()-1, f(xs).max()+1) фиксирует границы оси Y по значениям функции. Почему берём min/max именно от xs и f(xs) Потому что это левые/правые границы, где мы считали и рисовали функцию.

🔵plt.show(block=False) — показывает окно не блокируя выполнение кода.

plt.ion()
fig, ax = plt.subplots()
ax.grid(True)
ax.plot(xs, f(xs), label="f(x)")
pt = ax.scatter([x], [f(x)], c='red', s=50)
ax.set_xlim(xs.min(), xs.max())
ax.set_ylim(f(xs).min()-1, f(xs).max()+1)
plt.show(block=False)


5⃣ Самое важное: градиентный спуск и анимация

🔵Это и есть обновление по формуле 🟰 xₖ₊₁ = xₖ - λ * (2x - 5)) 🟰Если lr = 0.5 ➡️ сразу попадаем в глобальный минимум

🔵pt — это объект, который вернул 🟰 pt = ax.scatter([x], [f(x)], c='red', s=50) 🟰

for _ in range(N):
x = x - lr * df(x) # шаг: x_{k+1} = x_k - λ f'(x_k)
pt.set_offsets([[x, f(x)]]) # кладет новые (x, y) в объект точки (грубо говоря, это обновление уже нарисованной точки, будет переносить маркер в новые корды)
fig.canvas.draw_idle() # Рисует содержимое окна ; перерисовывает
plt.pause(0.03) # фигура перерисовывается + пазуа


6⃣ Фиксируем результаты:

plt.ioff()   # выключить интерактив
ax.scatter([x], [f(x)], c='blue', s=50, label="финал") # финальная точка (это куда мы пришли, глобальный минимум)
ax.axvline(2.5, ls='--', label="x* = 2.5") # вертикальная линия минимума
ax.legend()
print(x)
plt.show()


‼️ Теперь пройдемся по логике кода (САМОЕ САМОЕ ВАЖНОЕ): мы взяли 400 точек по оси x ➡️подставляем каждую точку в функцию f(x) ➡️ ax.plot соединяет точки линией (xs — это x корды, f(xs) — это y корды) ➡️ далее, у нас есть текущая точка x, считаем производную f'(x) и делаем шаг вниз (это антиградиент) ➡️ f'(x) задает направление и масштаб, λ — длина шага
Please open Telegram to view this post
VIEW IN TELEGRAM
3221
Сегодня пост
5331
👨‍💻 Всем ку! Заждались? Сегодня разбираем интересное задание, в последующем разберем несколько решений.

⬇️ ВЕСЬ МАТЕРИАЛ В КОММЕНТАРИЯХ ⬇️

⚙️ Итак, надеюсь, задание вы прочитали, теперь приступаем:

0⃣ Что нам вообще нужно

‼️ Начнем с формулировки "восстановления/аппроксимации" функции. Это значит, что нам нужно заменить (ИЛИ ПРИБЛИЗИТЬ) нашу функцию🟰 f(x) = 0.1x² - sin(x) + 5 🟰 кубическим полиномом (это который 🟰a(x) = w₀ + w₁... 🟰таким образом, чтобы подобранные веса w делали среднеквадратическую ошибку MSE между a(x) — (тот самый полином) и f(x) МИНИМАЛЬНОЙ НА СЕТКЕ [-5, 5]

‼️ Если не поняли, могу сказать по-другому: нам нужно подобрать веса w в кубическом полиноме a(x) таким образом, чтобы MSE между a(x) и f(x) на отрезке [-5, 5] была МИНИМАЛЬНЫМ.

1⃣ В общем, подбираем коэффициенты w, но все по порядку:

🔵Нам нужны данные для обучения и сама функция: у нас по условию уже есть точки x на отрезке [-5. 5] и тру-значения y = f(x), функция также дана

import numpy as np

# исходная функция, которую нужно аппроксимировать моделью a(x)
def func(x):
return 0.1 * x**2 - np.sin(x) + 5


# здесь объявляйте необходимые функции


coord_x = np.arange(-5.0, 5.0, 0.1) # значения по оси абсцисс [-5; 5] с шагом 0.1
coord_y = func(coord_x) # значения функции по оси ординат

sz = len(coord_x) # количество значений функций (точек)
eta = np.array([0.1, 0.01, 0.001, 0.0001]) # шаг обучения для каждого параметра w0, w1, w2, w3
w = np.array([0., 0., 0., 0.]) # начальные значения параметров модели
N = 200 # число итераций градиентного алгоритма


👨‍💻 Все что вы видите сверху — это все, что у нас есть, теперь будем думать:

2⃣ Наша следующая функция — features, она будет строить матрицу признаков S с колонками [1, x, x², x³].

def features(x):
x = np.asarray(x)
return np.stack([np.ones_like(x), x, x**2, x**3], axis=1)


🔵Функция np.asarray() в библиотеке NumPy — используется для преобразования входных данных в объект ndarray.

🔵ndarray (N-dimensional array) — класс многомерных массивов в библиотеке NumPy

🔵Входные данные могут быть в виде списков, кортежей или других объектов, похожих на массивы. Если входные данные уже являются массивом NumPy, функция не создаёт копию

🔵В нашем коде делает из входа (список/массив) numpy-вектор формы (n,).
А нужно это, чтобы дальше работали векторные операции x**2, x**3


🔵np.ones_like(x) — делает массив единиц такой же формы и типа, как x. Это столбец для свободного члена w₀ — форма также (n, ) — т.е вектор из n единиц. В нашей функции признаков этот вектор из единиц идёт как первый столбец

Что такое формы (n,), (n,1), (n,4)

Я уже как-то разбирал данный момент, но вернуться стоит:


🟢 (n,) — одномерный вектор длины n — это просто линейный массив...

💤 СКОРО ПРОДОЛЖИМ
Please open Telegram to view this post
VIEW IN TELEGRAM
3321
🔤🔤🌹🌷 5️⃣

👨‍💻 В дополнении к формам массивов:

🟢(n,) — одномерный вектор длины n. Нет строк/столбцов, просто линейный массив, форма (3, ) буде выглядеть как то так:

x = np.array([10., 20., 30.])
x.shape # (3, )
------------
[10. 20. 30.]


🟢(n, 1) — двумерная матрица: n строк, 1 столбец, массив форму (3, 1) буде выглядеть вот так:

x_col = x.reshape(-1, 1)
x_col.shape # (3, 1)
------------
[[10.]
[20.]
[30.]]


🟢(n, 4) — матрица: n строк, 4 столбца

S = np.column_stack([np.ones_like(x), x, x**2, x**3])
S.shape
-------------
[[ 1. 10. 100. 1000.]
[ 1. 20. 400. 8000.]
[ 1. 30. 900. 27000.]]


⬇️ ПОЛЕЗНЫЕ ССЫЛОЧКИ ВНИЗУ ⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
2111
👨‍💻 Для функции f(x) = x² - 4x, стартовое значение возьмем x₀ = 3, шаг обучение (он же learning rate) η = 0.1

Какой будет x₁ после одного шага градиентного спуска?
Anonymous Quiz
0%
2.4
0%
3.4
80%
2.8
0%
3.2
0%
3.8
0%
3.6
20%
2.0
0%
1.8
Please open Telegram to view this post
VIEW IN TELEGRAM
111
Ответ выложу позже, пока думайте 💭
Please open Telegram to view this post
VIEW IN TELEGRAM
111
⬇️ НЕ ЗАБЫВАЕМ ПРО ЧАТ ГАЙС ⬇️

ЗАХОДИМ СЮДА
Please open Telegram to view this post
VIEW IN TELEGRAM
1
CodeLab
если что тут ответ 1,3, 4