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

Обсуждение, новости, материал и сплетни — все здесь https://t.me/CodeLabMLChat
Download Telegram
👨‍💻Всем ку! Надеюсь, вы с невероятным кайфом проводите свои летние каникулы! Хочу разобрать до конца код:

📊 В посте сверху мы импортировали все нужное и прописали первую функцию polynomial. Еще один важный момент — многочлен:

🟰 2 * x⁰ + 0 * x¹ + (-1) * x² = 2 - x ** 2 🟰— по сути, обычная парабола

3⃣ Следующая функция — draw_polynomial (строит график многочлена по множеству иксов):

def draw_polynomial(coefs):
n = len(coefs)
x = np.linspace(-1, 1, 1000)
y = sum([coefs[i] * x ** i for i in range(len(coefs))])
plt.plot(x, y, linestyle = '-', color = 'black', label = 'True polynom')


Что мы имеем на данном этапе? У нас есть две функции: polynomial() и draw_polynomial()первая считает конкретные y для сгенерированных точек с шумом, вторая показывает настоящую функцию на графике.

‼️ Еще один немаловажный момент: Как рисуется наша парабола? Суть в том, что нам нужно построить график функции:

🟰y = 2 - x²🟰 или 🟰y = 2 + 0·x - 1·x²🟰

🔵Сначала, создаем точки по оси X: получаем массив из 1000 точек от -1 до 1

x = np.linspace(-1, 1, 1000)

# [-1. -0.998 -0.996 ... 0.996 0.998 1.0]

🔵Далее, нам нужно посчитать Y для каждого X (Применяем наш многочлен и подставляем каждый X в Y) — получаем массив Y

y = sum([coefs[i] * x ** i for i in range(len(coefs))])

# [1. 1.003996 1.007984 ... 1.007984 1.003996 1.0]


🔵 Теперь рисуем все:

plt.plot(x, y, linestyle='-', color='black')

y

2 | ●
1 | ● ●
0 +----------------→ x
-1 0 1


4⃣ Создаем списки для хранения (X - значения x, Y - y)

X = []
Y = []


5⃣ Генерируем точки. Будем делать 40 точек x из диапазона [-1, 1] и :

for i in range(40):
x = random.uniform(-1, 1) # Берем случайное значение от 1 до 1
y = polynomial(coefs, x) + random.gauss(0, 0.1) # Это наша формула мнргочлена + шум
X.append(x)
Y.append(y)


6⃣‼️ Главная функция (обучение + визуал):

def train_and_plot_polynomial_regression(X, Y, degree):
X = np.array(X).reshape(-1, 1)
Y = np.array(Y)


🟢Преобразуем списки в numpy массивы

    X = np.array(X).reshape(-1, 1) # X превращаем в столбец
Y = np.array(Y)


🟢Создаем полиномиальные признаки (В нашем случае степень будет 2) — X ➡️ [1, x, x²]. Мы по сути создаем объект, который расширяет признаки, добавляя степени x

    poly = PolynomialFeatures(degree=degree)


🟢Тут мы и превращаем обычные x в полиномиальные признаки.

    X_poly = poly.fit_transform(X)


🔵 Допустим, у нас был массив [[0.1], [0.2], ...]), применяем fit_transform при degree = 2 ➡️ получаем:

[[1, 0.1, 0.01],
[1, 0.2, 0.04],
...
]

# Наша запись теперь выяглидит подобно [x⁰, x¹, x²]


7⃣ Создаем объект линейной регрессии + обучаем ее на расширенных полиномиальных признаках X_poly и результатах Y

model = LinearRegression()
model.fit(X_poly, Y


‼️ Полиномиальная регрессия — это по сути линейная регрессия, но с нелинейными признаками. Она расширяет линейную модель путём добавления новых признаков, которые являются степенями исходных признаков.


8⃣ Создаем 100 равномерных точек X от минимум дол максимума, чтобы нарисовать линию модели:

P.S Это новые x-корды, чтобы красиво построить график

X_plot = np.linspace(np.min(X), np.max(X), 100).reshape(-1, 1) # reshape делает из вектора столбец


0⃣ Преобразуем эти 100 точек x в полиномиальные признаки и делаем предсказания (применяем к X полиномиальные признаки):

X_plot_poly = poly.transform(X_plot)
Y_plot_poly = model.predict(X_plot_poly) # Делаем предсказания модели
Please open Telegram to view this post
VIEW IN TELEGRAM
3222
👨‍💻 Всем ку, решаем быстренько и четенько одно задание со степика:

💬 Вот смотрите и думаете, как это решать

0⃣ Значит так, для начала, переписываем все, что имеем:

import numpy as np

def func(x):
return 0.5 * x**2 - 0.1 * 1/np.exp(-x) + 0.5 * np.cos(2*x) - 2.

coord_x = np.arange(-5.0, 5.0, 0.1)
coord_y = func(coord_x)

sz = len(coord_x)


🟢 Готово! Что мы сейчас написали? У нас объявлена функция, есть return, который возвращает значения, тут у нас и парабола, и экспонента, и косинус есть.

🟢 Еще у нас есть coord_x и coord_y:

🔵coord_x — Это 100 точек, в которых будем проверять и модель и нашу функцию

🔵coord_y — Это наши правильные, с ними мы будем сравнивать значения нашей будущей модели

🟢 Еще есть sz — просто переменная для количества точек (их 100, можете сами посчитать)

1⃣ Теперь включаем логику:

‼️ Нас просят посчитать значение среднего эмпирического риска (напоминаю, это средняя сумма ошибок на всей выборке).

🟰 Q(a, X)) = 1/n * ∑ loss(a, X) 🟰— Как самый наикрутейший админ, даже напишу формулу среднего эмпирического риска

💬 Думаем дальше: Чего нам не хватает Нам не хватает предсказаний модели (a). Думаем еще глубже: Чтобы нам найти (a), нам необходимо прописать веса модели:

w = [-1.59, -0.69, 0.278, 0.497, -0.106]


🟢 Прописали! Эти веса управляют свободным членом (bias), коэффициентами при x и , синусом и косинусом.

2⃣ Хорошо, веса есть! Теперь сама модель:

model_y = (
w[0] +
w[1] * coord_x +
w[2] * coord_x ** 2 +
w[3] * np.cos(2 * coord_x) +
w[4] * np.sin(2 * coord_x)

)


🟢 Получаем модель в виде формулы, в нее мы также подаем coord_x (Это еще один вызов функции на всех точках coord_x). Что происходит? Мы берем все 100 точек x из coord_x ➡️ подставляем в формулу модели ➡️ умножаем их на веса ➡️ складываем и готово

‼️ Вот тут вы должны были уловить главную мысль:

🟢В начале кода у нас был первый вызов:

coord_y = func(coord_x)


🟢Мы подали 100 точек coord_x в функцию f(x) и получили истинные значения.

🟢 Далее, происходит второй вызов функции:

model_y = (
w[0] +
w[1] * coord_x +
w[2] * coord_x ** 2 +
w[3] * np.cos(2 * coord_x) +
w[4] * np.sin(2 * coord_x)
)


‼️ На тех же 100 точках coord_x мы запускаем свою модель с весами w ➡️ получаем предсказания от модели.

3⃣ Теперь находим абсолютную функцию потерь, тут то мы и сравниваем насколько далеко наша моделька ошиблась на каждой точке (ошибка по модулю):

Losses = abs(model_y - coord_y)


🟢 Можете вывести предсказания обеих моделей и глянуть сами:

print(coord_y)
print('----------------------------------------')
print(model_y)


4⃣ Теперь средний эмпирический риск (cредняя ошибка по всем точкам):

Q = np.mean(Losses)


5⃣ По сути готово, но еще один момент:

🟢В коде была такая строчка, как:

sz = len(coord_x)


🟢Вот пример того, как эта строчка могла бы вписаться в код:

Q = 1/sz * sum([ Losses(model_y(x, w), func(x)) for x in coord_x ])
Please open Telegram to view this post
VIEW IN TELEGRAM
3222
Forwarded from CodeLab ML
📊 Какая метрика наиболее устойчива к выбросам в регрессии?
Anonymous Quiz
19%
A) MAE (Mean Absolute Error)
31%
B) MSE (Mean Squared Error)
25%
C) RMSE (Root Mean Squared Error)
25%
D) R² (коэффициент детерминации)
2222
Только попробуйте ответить неправильно
3221
🟢 Что может означать подобное выражение?

🟰w = (X.T @ y) @ np.linalg.inv(X.T @ X)🟰

‼️ Прежде всего — это формула вычисления весов (характерна для задач регрессии или классификации по прямой)


🟰w = (X.T @ y) @ np.linalg.inv(X.T @ X)🟰

🔵X — матрица признаков, например, [1, x1, x2] )

🔵y — вектор целевых значений

🔵X.T — транспонированная матрица X

🟢Допустим, мы имеем такой вот X:

X =
[[1, 5.8, 1.2],
[1, 5.6, 1.5],
[1, 6.5, 1.5]]


🔵X.shape = (3, 3) ➡️ 3 точки, каждая имеет 3 признака (включая 1 для смещения w0)

🟢Теперь y:

y = [-1, -1, 1]


🔵y.shape == (3,) ➡️ просто вектор из 3 чисел

🟢Транспонируем X.T:

X.T =
[[1.0, 1.0, 1.0], # w0
[5.8, 5.6, 6.5], # x1
[1.2, 1.5, 1.5]] # x2


🔵X.T.shape = (3, 3) ➡️ транспонировали (строки стали столбцами)

🟢Теперь матрица XTX = X.T @ X:

🔵XTX = (3, 3) @ (3, 3)

🔵XTX.shape = (3, 3)

🟢 inv_XTX = np.linalg.inv(X.T @ X)обратная матрица размерность не меняет, поэтому inv_XTX.shape == (3, 3)

🟢Матрица XTy = X.T @ y

🔵XTy = X.T @ y

🔵X.T = (3, 3)
🔵y = (3,)

🔵XTy.shape == (3,) → вектор из 3 чисел

🟢Результат получается таким:

🔵w = inv_XTX @ XTy

‼️🔵 (3, 3) @ (3,) = (3,)

👨‍💻 Вот вам некоторые необходимы понятия:

2⃣ Существуют объекты и признаки: размерность наших данных, к примеру. равна (3,2) — то есть, 3 разных объекта (их мы и классифицируем) и 2 признака на каждый объект

3⃣ Затем, мы добавляем bias и получаем размерность (3, 3), что вполне логично.

X = [(1,  5.6, 1.5),
(1, 6.5, 1.5),
(1, 6.1, 1.3)
]

X.shape == (3, 3)


4⃣ X.T — транспонируем, матрица квадратная, ничего кароч не меняется.

X.T.shape = (3, 3)


5⃣ X.T @ y — перемножаем на метки нашу транспонированную матрицу — получаем размерность (3,) — по сути просто каждый элемент в X.T (bias + признаки) перемножаем на вектор и ‼️ суммируем.

Вот такие вот дела
Please open Telegram to view this post
VIEW IN TELEGRAM
2111
👀
Please open Telegram to view this post
VIEW IN TELEGRAM
📱 Если у модели высокое смещение (bias) и низкая дисперсия — это значит, что:

📊 P.S| Дисперсия это насколько сильно разбросаны значения/предсказания вокруг среднего — это изменчивость предсказаний модели при изменении данных.
Anonymous Quiz
45%
A) Модель точно предсказывает тренировочные данные, но плохо на тесте
9%
B) Модель хорошо предсказывает тест, но переобучена
27%
C) Модель слишком проста и недообучена
18%
D) Модель идеально сбалансирована
2111
👀Самое интересное — это аниме тянка и 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