✍️ Разбираем сложные задачи прошедшей недели
1️⃣ Автокодировщик (англ. autoencoder) — это специальная архитектура нейронных сетей, основная идея которой научиться сжимать входные данные в компактное представление и затем восстанавливать эти данные обратно к их исходному виду или как можно ближе к нему.
Автокодировщик состоит из двух частей: энкодера и декодера. Энкодер переводит входной сигнал в его представление, а декодер восстанавливает сигнал по этому представлению. При этом в центре нейронной сети создаётся узкий слой — бутылочное горлышко. Количество нейронов в нём должно быть на порядок меньше, чем у входа. Так мы заставляем нейросеть находить в объекте самую важную информацию и передавать через бутылочное горлышко только её.
2️⃣ В этой задаче сначала мы создаём numpy-массив, состоящий только из элементов-единиц. Автоматически используется тип данных numpy.float64 (если не указать иное). torch.from_numpy в свою очередь автоматически наследует тип данных массива numpy.
#разбор_задач
1️⃣ Автокодировщик (англ. autoencoder) — это специальная архитектура нейронных сетей, основная идея которой научиться сжимать входные данные в компактное представление и затем восстанавливать эти данные обратно к их исходному виду или как можно ближе к нему.
Автокодировщик состоит из двух частей: энкодера и декодера. Энкодер переводит входной сигнал в его представление, а декодер восстанавливает сигнал по этому представлению. При этом в центре нейронной сети создаётся узкий слой — бутылочное горлышко. Количество нейронов в нём должно быть на порядок меньше, чем у входа. Так мы заставляем нейросеть находить в объекте самую важную информацию и передавать через бутылочное горлышко только её.
2️⃣ В этой задаче сначала мы создаём numpy-массив, состоящий только из элементов-единиц. Автоматически используется тип данных numpy.float64 (если не указать иное). torch.from_numpy в свою очередь автоматически наследует тип данных массива numpy.
#разбор_задач
❤2
✍️ Разбираем задачи прошедшей недели
1️⃣ По умолчанию для новых тензоров в PyTorch параметр requires_grad установлен в False. Он указывает, нужно ли вычислять градиенты для тензора во время операций обратного распространения ошибки. Чтобы добиться этого, следует явно установить requires_grad=True при создании тензора.
2️⃣ Для классической линейной регрессии действует предположение о том, что дисперсия ошибок модели остаётся постоянной на протяжении всех значений независимых переменных. Гетероскедастичность — это нарушение данного предположения. То есть наличие гетероскедастичности можно заподозрить, если отклонения наблюдений от линии выборочной регрессии (остатки) достаточно сильно различаются.
3️⃣ Здесь нужно считать так:
- Первое умножение весов и прибавление смещений: 2*1 + 1 и 2*2 — 5 —> 3 и -1.
- Первое применение Relu: relu(3) = 3 и relu(-1) = 0.
- Второе умножение весов и прибавление смещений: 3*-2 + 0*4 = —6. —6 + 10 = 4.
- Второе применение Relu: relu(4) = 4.
4️⃣ Название Adam можно расшифровать как ADAptive Momentum. Этот метод объединяет две идеи: использование момента и адаптивных скоростей обучения. Вместо того чтобы адаптировать скорость обучения параметров на основе среднего первого момента, как в RMSProp, Adam также использует среднее значение вторых моментов градиентов.
5️⃣ Хорошее объяснение для этой задачи было дано в комментариях.
#разбор_задач
1️⃣ По умолчанию для новых тензоров в PyTorch параметр requires_grad установлен в False. Он указывает, нужно ли вычислять градиенты для тензора во время операций обратного распространения ошибки. Чтобы добиться этого, следует явно установить requires_grad=True при создании тензора.
2️⃣ Для классической линейной регрессии действует предположение о том, что дисперсия ошибок модели остаётся постоянной на протяжении всех значений независимых переменных. Гетероскедастичность — это нарушение данного предположения. То есть наличие гетероскедастичности можно заподозрить, если отклонения наблюдений от линии выборочной регрессии (остатки) достаточно сильно различаются.
3️⃣ Здесь нужно считать так:
- Первое умножение весов и прибавление смещений: 2*1 + 1 и 2*2 — 5 —> 3 и -1.
- Первое применение Relu: relu(3) = 3 и relu(-1) = 0.
- Второе умножение весов и прибавление смещений: 3*-2 + 0*4 = —6. —6 + 10 = 4.
- Второе применение Relu: relu(4) = 4.
4️⃣ Название Adam можно расшифровать как ADAptive Momentum. Этот метод объединяет две идеи: использование момента и адаптивных скоростей обучения. Вместо того чтобы адаптировать скорость обучения параметров на основе среднего первого момента, как в RMSProp, Adam также использует среднее значение вторых моментов градиентов.
5️⃣ Хорошее объяснение для этой задачи было дано в комментариях.
#разбор_задач
👍7
✍️ Очередной воскресный разбор задач
1️⃣ Log Loss — это одна из функций потерь, используемая в задаче классификации. Основывается на вероятностной модели. Чтобы вычислить вероятность получения исходной выборки согласно предсказаниям модели, перемножаются вероятности каждого отдельного y при условии набора признаков x. Получившуюся таким образом функцию правдоподобия нужно максимизировать. Однако максимизировать произведение достаточно сложно, поэтому берётся логарифм. Кроме того, выражение преобразуется для того, чтобы от задачи максимизации перейти к задаче минимизации.
Причина, по которой Log Loss сильнее штрафует за уверенные и неверные прогнозы, заключается в свойствах логарифмической функции. Когда модель делает уверенное предсказание (то есть, pi близко к 1 для истинного класса 1 или pi близко к 0 для истинного класса 0), и это предсказание верно, логарифмический компонент приближается к 0, что приводит к меньшему значению потерь. Однако, если модель делает уверенное, но ошибочное предсказание (pi близко к 1, когда истинный класс 0, или pi близко к 0, когда истинный класс 1), логарифмический компонент стремится к бесконечности.
2️⃣ Рассмотрим, как работают операторы and и or в Python.
▪️and возвращает первый операнд, если он ложен, иначе возвращает второй операнд.
▪️or возвращает первый операнд, если он истинен, иначе возвращает второй операнд.
Таким образом, в этой задаче в переменную a (5 and 10) запишется 10. В переменную b (5 or 10) запишется 5. Верным ответом будет 30.
3️⃣ В данном объединении используется метод outer. Он работает как FULL JOIN в SQL, то есть полное внешнее объединение. Включаются все строки из обеих таблиц. Если совпадений по ключу нет, в результирующем DataFrame для отсутствующих значений вставляется NaN.
#разбор_задач
1️⃣ Log Loss — это одна из функций потерь, используемая в задаче классификации. Основывается на вероятностной модели. Чтобы вычислить вероятность получения исходной выборки согласно предсказаниям модели, перемножаются вероятности каждого отдельного y при условии набора признаков x. Получившуюся таким образом функцию правдоподобия нужно максимизировать. Однако максимизировать произведение достаточно сложно, поэтому берётся логарифм. Кроме того, выражение преобразуется для того, чтобы от задачи максимизации перейти к задаче минимизации.
Причина, по которой Log Loss сильнее штрафует за уверенные и неверные прогнозы, заключается в свойствах логарифмической функции. Когда модель делает уверенное предсказание (то есть, pi близко к 1 для истинного класса 1 или pi близко к 0 для истинного класса 0), и это предсказание верно, логарифмический компонент приближается к 0, что приводит к меньшему значению потерь. Однако, если модель делает уверенное, но ошибочное предсказание (pi близко к 1, когда истинный класс 0, или pi близко к 0, когда истинный класс 1), логарифмический компонент стремится к бесконечности.
2️⃣ Рассмотрим, как работают операторы and и or в Python.
▪️and возвращает первый операнд, если он ложен, иначе возвращает второй операнд.
▪️or возвращает первый операнд, если он истинен, иначе возвращает второй операнд.
Таким образом, в этой задаче в переменную a (5 and 10) запишется 10. В переменную b (5 or 10) запишется 5. Верным ответом будет 30.
3️⃣ В данном объединении используется метод outer. Он работает как FULL JOIN в SQL, то есть полное внешнее объединение. Включаются все строки из обеих таблиц. Если совпадений по ключу нет, в результирующем DataFrame для отсутствующих значений вставляется NaN.
#разбор_задач
❤4
✍️ Разбираем задачи прошедшей недели
1️⃣ В строковых литералах Python обратный слеш \ используется для экранирования специальных символов, таких как \n для новой строки или \t для табуляции. В данном случае двойной обратный слеш \\ интерпретируется как один обратный слеш, а символ t после него остаётся просто буквой. Вывод будет — '2\t4'.
2️⃣ Кросс-валидация, по сути, эмулирует наличие тестовой выборки, которая не участвует в обучении, но для которой известны правильные ответы. При этом можно систематически изменять гиперпараметры модели, чтобы найти такую комбинацию, которая даёт лучшую производительность на разных подмножествах данных. Это обычно достигается с помощью таких методов, как Grid Search или Random Search.
3️⃣ Функция np.linalg.solve(A, b) решает систему уравнений, которая выглядит так:
3x1+x2=9
x1+2x2=8
Её решением будет [2. 3.]
#разбор_задач
1️⃣ В строковых литералах Python обратный слеш \ используется для экранирования специальных символов, таких как \n для новой строки или \t для табуляции. В данном случае двойной обратный слеш \\ интерпретируется как один обратный слеш, а символ t после него остаётся просто буквой. Вывод будет — '2\t4'.
2️⃣ Кросс-валидация, по сути, эмулирует наличие тестовой выборки, которая не участвует в обучении, но для которой известны правильные ответы. При этом можно систематически изменять гиперпараметры модели, чтобы найти такую комбинацию, которая даёт лучшую производительность на разных подмножествах данных. Это обычно достигается с помощью таких методов, как Grid Search или Random Search.
3️⃣ Функция np.linalg.solve(A, b) решает систему уравнений, которая выглядит так:
3x1+x2=9
x1+2x2=8
Её решением будет [2. 3.]
#разбор_задач
👍6
✍️ Воскресный разбор задач
Сегодня рассмотрим одну задачу, которая поднимает любопытный вопрос.
🔹 При выполнении кода np.array(0) / np.array(0) Python выдаст предупреждение о делении на ноль и вернёт nan (Not a Number). Это стандартное поведение для таких операций.
🔹 При выполнении операции целочисленного деления np.array(0) // np.array(0) Python также сгенерирует предупреждение, но выведет ноль. Это не совсем нормальное поведение. И разработчики NumPy об этом знают.
В репозитории проекта существует issue с описанием проблемы. Автор поясняет, что целью было реализовать поведение при делении на ноль у целых чисел, у которых нет nan. Было решено просто взять рандомное значение (0) и возвращать его вместо nan. Однако, по мнению автора, это может порождать неожиданные проблемы, так как отловить ошибку становится затруднительно. С ним, впрочем, другие члены команды не согласны. Issue открыт до сих пор. Поэтому единственный выход — помнить о таком исключении.
#разбор_задач
Сегодня рассмотрим одну задачу, которая поднимает любопытный вопрос.
🔹 При выполнении кода np.array(0) / np.array(0) Python выдаст предупреждение о делении на ноль и вернёт nan (Not a Number). Это стандартное поведение для таких операций.
🔹 При выполнении операции целочисленного деления np.array(0) // np.array(0) Python также сгенерирует предупреждение, но выведет ноль. Это не совсем нормальное поведение. И разработчики NumPy об этом знают.
В репозитории проекта существует issue с описанием проблемы. Автор поясняет, что целью было реализовать поведение при делении на ноль у целых чисел, у которых нет nan. Было решено просто взять рандомное значение (0) и возвращать его вместо nan. Однако, по мнению автора, это может порождать неожиданные проблемы, так как отловить ошибку становится затруднительно. С ним, впрочем, другие члены команды не согласны. Issue открыт до сих пор. Поэтому единственный выход — помнить о таком исключении.
#разбор_задач
👍4❤1
✍️ Разбор задач прошедшей недели
1️⃣ У нас были два вопроса по np.nan. Давайте поясним, что это вообще такое.
NaN — это сокращение для Not a number. Это значит, что np.nan применяют для обозначения нечисловых значений. В NumPy nan имеет тип данных float. Его можно использовать как заглушку для значений в массиве, если для вас неважно, каким было оригинальное значение.
▪️np.nan не равно себе же. Выражение np.nan == np.nan всегда будет возвращать False. Поэтому в некоторых случаях следует пользоваться функцией np.isnan().
▪️Любая арифметическая операция с np.nan будет возвращать np.nan.
2️⃣ В этой задаче была допущена банальная синтаксическая ошибка. Для доступа к элементам списка следует использовать квадратные скобки. Правильной записью была бы такая: print(phrase[0]). И вывела бы она 'Добрый день'.
Нередко именно такие глупые ошибки могут стать загвоздкой и мешать вашему коду корректно исполняться 👾
#разбор_задач
1️⃣ У нас были два вопроса по np.nan. Давайте поясним, что это вообще такое.
NaN — это сокращение для Not a number. Это значит, что np.nan применяют для обозначения нечисловых значений. В NumPy nan имеет тип данных float. Его можно использовать как заглушку для значений в массиве, если для вас неважно, каким было оригинальное значение.
▪️np.nan не равно себе же. Выражение np.nan == np.nan всегда будет возвращать False. Поэтому в некоторых случаях следует пользоваться функцией np.isnan().
▪️Любая арифметическая операция с np.nan будет возвращать np.nan.
2️⃣ В этой задаче была допущена банальная синтаксическая ошибка. Для доступа к элементам списка следует использовать квадратные скобки. Правильной записью была бы такая: print(phrase[0]). И вывела бы она 'Добрый день'.
Нередко именно такие глупые ошибки могут стать загвоздкой и мешать вашему коду корректно исполняться 👾
#разбор_задач
👍4
✍️ Разбор задач прошедшей недели
1️⃣ Функция DataFrame.rename в Pandas позволяет переименовать столбцы. Однако, как и многие другие функции, она применяется не inplace по умолчанию, то есть она возвращает новый объект DataFrame с изменениями, не затрагивая исходный объект. Чтобы изменения применились к исходному объекту DataFrame, необходимо использовать аргумент inplace=True.
По этой причине код выведет столбец с названием Profit.
2️⃣ Функция divmod в Python принимает два аргумента и возвращает пару чисел, состоящую из частного и остатка от деления первого аргумента на второй. В случае с divmod(15, 4) выведется кортеж (3, 3). Таким образом, sum в качестве аргументов передаётся следующее: (3, 3) и 2. 2 служит здесь начальным значением для суммирования, к которому добавляется сумма элементов кортежа (3, 3).
3️⃣ Наивный Байес — это довольно простой алгоритм. Он работает на предположении, что все признаки в наборе данных независимы друг от друга. Благодаря этому алгоритм может использовать принцип условной вероятности. Так, он учитывает вероятности появления определённых признаков при наличии конкретного класса.
В отличие от многих других алгоритмов машинного обучения Наивный Байес не рассчитывает расстояния между точками, из-за этого он не чувствителен к масштабу признаков.
#разбор_задач
1️⃣ Функция DataFrame.rename в Pandas позволяет переименовать столбцы. Однако, как и многие другие функции, она применяется не inplace по умолчанию, то есть она возвращает новый объект DataFrame с изменениями, не затрагивая исходный объект. Чтобы изменения применились к исходному объекту DataFrame, необходимо использовать аргумент inplace=True.
По этой причине код выведет столбец с названием Profit.
2️⃣ Функция divmod в Python принимает два аргумента и возвращает пару чисел, состоящую из частного и остатка от деления первого аргумента на второй. В случае с divmod(15, 4) выведется кортеж (3, 3). Таким образом, sum в качестве аргументов передаётся следующее: (3, 3) и 2. 2 служит здесь начальным значением для суммирования, к которому добавляется сумма элементов кортежа (3, 3).
3️⃣ Наивный Байес — это довольно простой алгоритм. Он работает на предположении, что все признаки в наборе данных независимы друг от друга. Благодаря этому алгоритм может использовать принцип условной вероятности. Так, он учитывает вероятности появления определённых признаков при наличии конкретного класса.
В отличие от многих других алгоритмов машинного обучения Наивный Байес не рассчитывает расстояния между точками, из-за этого он не чувствителен к масштабу признаков.
#разбор_задач
❤5
✍️ Воскресный разбор задач
1️⃣ Поговорим о Центральной предельной теореме (ЦПТ).
Можно рассматривать её вместе с Законом больших чисел (ЗБЧ). ЗБЧ гласит, что если некий эксперимент, результатом которого является число (случайная величина с матожиданием μ), провести много раз и усреднить результаты, то этот усреднённый результат, скорее всего, будет близок к μ. Это можно интерпретировать относительно среднего выборки следующим образом: чем больше размер выборки, тем ближе её среднее к среднему генеральной совокупности.
ЦПТ утверждает, что распределение суммы таких независимых случайных величин приближается к нормальному, если количество испытаний или число респондентов достаточно велико. Это можно интерпретировать относительно среднего выборки следующим образом: когда размер выборки увеличивается, распределение средних этих выборок, вне зависимости от исходного распределения данных в генеральной совокупности, стремится к нормальному распределению. То есть одно из ключевых отличий ЦПТ от ЗБЧ заключается в том, что ЦПТ описывает форму распределения средних значений.
2️⃣ Этот код создаёт массив из чисел от 0 до 9 (np.arange(10)). Также он изменяет форму этого массива на двумерный с помощью метода reshape(2, -1), где 2 указывает на количество строк, а -1 позволяет NumPy автоматически вычислить необходимое количество столбцов (в данном случае это 5 столбцов). Затем код выводит на печать arr[0, -1]. Здесь 0 указывает на первую строку массива, а -1 указывает на последний элемент в этой строке. Таким образом, из первой строки ([0, 1, 2, 3, 4]) будет извлечён последний элемент, который равен 4.
#разбор_задач
1️⃣ Поговорим о Центральной предельной теореме (ЦПТ).
Можно рассматривать её вместе с Законом больших чисел (ЗБЧ). ЗБЧ гласит, что если некий эксперимент, результатом которого является число (случайная величина с матожиданием μ), провести много раз и усреднить результаты, то этот усреднённый результат, скорее всего, будет близок к μ. Это можно интерпретировать относительно среднего выборки следующим образом: чем больше размер выборки, тем ближе её среднее к среднему генеральной совокупности.
ЦПТ утверждает, что распределение суммы таких независимых случайных величин приближается к нормальному, если количество испытаний или число респондентов достаточно велико. Это можно интерпретировать относительно среднего выборки следующим образом: когда размер выборки увеличивается, распределение средних этих выборок, вне зависимости от исходного распределения данных в генеральной совокупности, стремится к нормальному распределению. То есть одно из ключевых отличий ЦПТ от ЗБЧ заключается в том, что ЦПТ описывает форму распределения средних значений.
2️⃣ Этот код создаёт массив из чисел от 0 до 9 (np.arange(10)). Также он изменяет форму этого массива на двумерный с помощью метода reshape(2, -1), где 2 указывает на количество строк, а -1 позволяет NumPy автоматически вычислить необходимое количество столбцов (в данном случае это 5 столбцов). Затем код выводит на печать arr[0, -1]. Здесь 0 указывает на первую строку массива, а -1 указывает на последний элемент в этой строке. Таким образом, из первой строки ([0, 1, 2, 3, 4]) будет извлечён последний элемент, который равен 4.
#разбор_задач
👍3❤2
✍️ Разбор сложных задач
1️⃣ AdaBoost — это классический алгоритм бустинга, то есть комбинирует слабые модели в одну сильную. В данном случае алгоритм усиливает классификаторы, объединяя их в комитет. Работает он так:
▫️Вызывает слабые классификаторы в цикле. Каждый классификатор делает своё предсказание;
▫️После каждого вызова обновляется распределение весов, которые отвечают за важность каждого из объектов для классификации. На каждой итерации веса каждого неверно классифицированного объекта возрастают, таким образом новый комитет классификаторов «фокусирует своё внимание» на этих объектах.
▫️В завершение каждой итерации эффективность каждого классификатора оценивается, и на основе этой оценки определяется его вес в окончательном решении. Если эффективность классификатора низкая, то и вес будет низким: его вклад в итоговую модель будет минимален.
2️⃣ Начиная с Python 3.7 словари в Python стали упорядоченными. Это означает, что они сохраняют порядок вставки элементов. Если вы добавите элементы в словарь, они будут возвращены в том порядке, в каком были добавлены, при итерации по словарю или его выводе.
3️⃣ Вот как происходит вычисление этого выражения:
▫️None and False выведет None. Если в цепочке and все операнды являются истиной, то результатом будет последнее значение. А если какой-либо из операндов является False, результатом будет первое ложное значение. None считается ложным значением. None and False выведет None.
▫️Если какой либо операнд в цепочке or является истиной, немедленно возвращается первое истинное значение. Таким образом, None or True выведет True.
#разбор_задач
1️⃣ AdaBoost — это классический алгоритм бустинга, то есть комбинирует слабые модели в одну сильную. В данном случае алгоритм усиливает классификаторы, объединяя их в комитет. Работает он так:
▫️Вызывает слабые классификаторы в цикле. Каждый классификатор делает своё предсказание;
▫️После каждого вызова обновляется распределение весов, которые отвечают за важность каждого из объектов для классификации. На каждой итерации веса каждого неверно классифицированного объекта возрастают, таким образом новый комитет классификаторов «фокусирует своё внимание» на этих объектах.
▫️В завершение каждой итерации эффективность каждого классификатора оценивается, и на основе этой оценки определяется его вес в окончательном решении. Если эффективность классификатора низкая, то и вес будет низким: его вклад в итоговую модель будет минимален.
2️⃣ Начиная с Python 3.7 словари в Python стали упорядоченными. Это означает, что они сохраняют порядок вставки элементов. Если вы добавите элементы в словарь, они будут возвращены в том порядке, в каком были добавлены, при итерации по словарю или его выводе.
3️⃣ Вот как происходит вычисление этого выражения:
▫️None and False выведет None. Если в цепочке and все операнды являются истиной, то результатом будет последнее значение. А если какой-либо из операндов является False, результатом будет первое ложное значение. None считается ложным значением. None and False выведет None.
▫️Если какой либо операнд в цепочке or является истиной, немедленно возвращается первое истинное значение. Таким образом, None or True выведет True.
#разбор_задач
👍6
✍️ Воскресный разбор задач
Сегодня рассмотрим одну задачу по свёртке.
При свёртке у нас есть ядро (kernel) — небольшая матрица весов. Это ядро «скользит» по входным данным, выполняя поэлементное умножение для той части данных, которую сейчас покрывает. Результаты перемножений ячеек суммируются в одном выходном пикселе.
В этой задаче хоть и не было прямо указано, но предполагалось, что размер выходного изображения (матрицы) должен остаться таким же, что и размер входного изображения. Для этого исходную матрицу можно дополнить «поддельными» пикселями вокруг. Тогда:
🟡 Ядро размещается поверх изображения так, чтобы его центр находился над текущим пикселем.
🟡 Элементы ядра умножаются на соответствующие элементы изображения под ними.
🟡 Результаты умножения суммируются, формируя новое значение для текущего пикселя.
Процесс повторяется для каждого пикселя изображения. Ядро последовательно «скользит» по всему изображению. Если используется ядро, которое в основном состоит из нулей с единицей по центру, как [[0, 0, 0], [0, 1, 0], [0, 0, 0]], каждый пиксель остаётся неизменным, поскольку только центральный пиксель умножается на 1, а все окружающие на 0. Это оставляет изображение без изменений после свёртки.
Мы можем проверить все ядра на изображении с помощью функции Filter2D() из OpenCV:
#разбор_задач
Сегодня рассмотрим одну задачу по свёртке.
При свёртке у нас есть ядро (kernel) — небольшая матрица весов. Это ядро «скользит» по входным данным, выполняя поэлементное умножение для той части данных, которую сейчас покрывает. Результаты перемножений ячеек суммируются в одном выходном пикселе.
В этой задаче хоть и не было прямо указано, но предполагалось, что размер выходного изображения (матрицы) должен остаться таким же, что и размер входного изображения. Для этого исходную матрицу можно дополнить «поддельными» пикселями вокруг. Тогда:
Процесс повторяется для каждого пикселя изображения. Ядро последовательно «скользит» по всему изображению. Если используется ядро, которое в основном состоит из нулей с единицей по центру, как [[0, 0, 0], [0, 1, 0], [0, 0, 0]], каждый пиксель остаётся неизменным, поскольку только центральный пиксель умножается на 1, а все окружающие на 0. Это оставляет изображение без изменений после свёртки.
Мы можем проверить все ядра на изображении с помощью функции Filter2D() из OpenCV:
from google.colab.patches import cv2_imshow
import cv2
import numpy as np
image = cv2.imread("dog.jpeg")
kernels = {
"1 kernel": np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]),
"2 kernel": np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]),
"3 kernel": np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]]),
"4 kernel": np.array([[1, 0, 0], [1, 0, 0], [1, 1, 1]])
}
for kernel in kernels.values():
convolved_image = cv2.filter2D(image, -1, kernel)
cv2_imshow(image)
cv2_imshow(convolved_image)
#разбор_задач
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2
✍️ Разбор задач прошедшей недели
1️⃣ В Python мы можем указывать изменяемые значения по умолчанию для функций, в том числе мы можем указать пустой список. Однако в этом случае код может повести себя неожиданным образом. Дело в том, что изменяемые значения по умолчанию сохраняются между вызовами функции.
В этой задаче когда функция func вызывается первый раз с func(1), параметр x принимает значение 1, а параметр y используется по умолчанию как пустой список []. Функция добавляет x в список y, который становится [1], и возвращает этот список. Когда функция func вызывается второй раз с func(2), параметр x принимает значение 2, а параметр y не передаётся явно, поэтому снова используется значение по умолчанию. y — это уже существующий список, содержащий [1]. Функция добавляет x в этот список, который становится [1, 2], и возвращает его.
2️⃣ Здесь стоит отметить, что изменение learning rate тоже вполне себе метод решения проблемы. Однако вопрос был о наиболее очевидном методе.
Начальные точки напрямую определяют, с какого места начнёт обучение нейросеть. Поэтому выбор различных начальных точек может привести к разным траекториям обучения, и, следовательно, увеличить шанс достижения глобального минимума.
#разбор_задач
1️⃣ В Python мы можем указывать изменяемые значения по умолчанию для функций, в том числе мы можем указать пустой список. Однако в этом случае код может повести себя неожиданным образом. Дело в том, что изменяемые значения по умолчанию сохраняются между вызовами функции.
В этой задаче когда функция func вызывается первый раз с func(1), параметр x принимает значение 1, а параметр y используется по умолчанию как пустой список []. Функция добавляет x в список y, который становится [1], и возвращает этот список. Когда функция func вызывается второй раз с func(2), параметр x принимает значение 2, а параметр y не передаётся явно, поэтому снова используется значение по умолчанию. y — это уже существующий список, содержащий [1]. Функция добавляет x в этот список, который становится [1, 2], и возвращает его.
2️⃣ Здесь стоит отметить, что изменение learning rate тоже вполне себе метод решения проблемы. Однако вопрос был о наиболее очевидном методе.
Начальные точки напрямую определяют, с какого места начнёт обучение нейросеть. Поэтому выбор различных начальных точек может привести к разным траекториям обучения, и, следовательно, увеличить шанс достижения глобального минимума.
#разбор_задач
❤4
✍️ Воскресный разбор сложных задач недели
1️⃣ L2-регрессия добавляет штраф к функции потерь, пропорциональный квадрату нормы коэффициентов. А L1-регрессия добавляет штраф, пропорциональный норме коэффициентов без возведения в квадрат. Таким образом, первый метод регуляризации стремится уменьшить влияние менее значимых признаков, уменьшая их коэффициенты, но редко приводит к тому, что они становятся строго равными нулю. А вот во втором случае может произойти зануление.
Поэтому если мы понимаем, что нам важны все признаки и не хотим избавляться от каких-то из них, лучше использовать L2-регрессию.
2️⃣ Давайте рассмотрим все методы трансформации данных из вопроса:
▫️Z-score — хороший выбор, если выбросы в данных не экстремальные. Однако по графику видно, что аномалии довольно значительные.
▫️Биннинг с квантильными границами — мог бы подойти, если бы данные были асимметричны, но в данном случае асимметрия частично вызвана несколькими экстремальными выбросами. Кроме того, мы хотим, чтобы модель обучилась линейной зависимости. Поэтому следует оставить показатель roomsPerPerson числовым, а не преобразовывать его в категории.
▫️Логарифмическое масштабирование — подошло бы, если бы данные подчинялись степенному закону. Однако эти данные подчиняются нормальному распределению.
▫️Clipping — подойдёт для начала анализа, так как в наборе данных присутствуют экстремальные выбросы. Можно убрать их перед применением других методов нормализации.
#разбор_задач
1️⃣ L2-регрессия добавляет штраф к функции потерь, пропорциональный квадрату нормы коэффициентов. А L1-регрессия добавляет штраф, пропорциональный норме коэффициентов без возведения в квадрат. Таким образом, первый метод регуляризации стремится уменьшить влияние менее значимых признаков, уменьшая их коэффициенты, но редко приводит к тому, что они становятся строго равными нулю. А вот во втором случае может произойти зануление.
Поэтому если мы понимаем, что нам важны все признаки и не хотим избавляться от каких-то из них, лучше использовать L2-регрессию.
2️⃣ Давайте рассмотрим все методы трансформации данных из вопроса:
▫️Z-score — хороший выбор, если выбросы в данных не экстремальные. Однако по графику видно, что аномалии довольно значительные.
▫️Биннинг с квантильными границами — мог бы подойти, если бы данные были асимметричны, но в данном случае асимметрия частично вызвана несколькими экстремальными выбросами. Кроме того, мы хотим, чтобы модель обучилась линейной зависимости. Поэтому следует оставить показатель roomsPerPerson числовым, а не преобразовывать его в категории.
▫️Логарифмическое масштабирование — подошло бы, если бы данные подчинялись степенному закону. Однако эти данные подчиняются нормальному распределению.
▫️Clipping — подойдёт для начала анализа, так как в наборе данных присутствуют экстремальные выбросы. Можно убрать их перед применением других методов нормализации.
#разбор_задач
👍5❤3
✍️ Разбор задач
Сегодня разберёмся, чем стохастический градиентный спуск (SGD) отличается от мини-пакетного (mini-batch).
Оба — оптимизационные алгоритмы, которые являются вариациями классического градиентного спуска. Для начала вспомним, как он работает.
У нас есть вектор признаков и вектор весов w. Допустим, мы выбрали какую-нибудь функцию потерь. Нам необходимо минимизировать её. Выберем для весов какое-то начальное приближение и вычислим результат на основе этого. По функции потерь посчитаем градиент, то есть вектор частных производных функции потерь по каждому из весов. Именно он поможет нам скорректировать веса w в нужно направлении. Иными словами, мы будем вычитать из вектора весов градиент, домноженный на какой-то шаг обучения.
🔹 В стохастическом градиентном спуске градиент функции считается на каждом шаге не как сумма градиентов от каждого элемента выборки, а как градиент от одного, случайно выбранного элемента.
🔹 В мини-пакетном градиентном спуске (mini-batch) градиент функции считается на каждом шаге как градиент от небольшой, случайно выбранной партии элементов (мини-пакета).
#разбор_задач
Сегодня разберёмся, чем стохастический градиентный спуск (SGD) отличается от мини-пакетного (mini-batch).
Оба — оптимизационные алгоритмы, которые являются вариациями классического градиентного спуска. Для начала вспомним, как он работает.
У нас есть вектор признаков и вектор весов w. Допустим, мы выбрали какую-нибудь функцию потерь. Нам необходимо минимизировать её. Выберем для весов какое-то начальное приближение и вычислим результат на основе этого. По функции потерь посчитаем градиент, то есть вектор частных производных функции потерь по каждому из весов. Именно он поможет нам скорректировать веса w в нужно направлении. Иными словами, мы будем вычитать из вектора весов градиент, домноженный на какой-то шаг обучения.
🔹 В стохастическом градиентном спуске градиент функции считается на каждом шаге не как сумма градиентов от каждого элемента выборки, а как градиент от одного, случайно выбранного элемента.
🔹 В мини-пакетном градиентном спуске (mini-batch) градиент функции считается на каждом шаге как градиент от небольшой, случайно выбранной партии элементов (мини-пакета).
#разбор_задач
👍6🔥3
✍️ Разбор сложных задач недели
1️⃣ Метод numpy.bincount используется для подсчёта количества вхождений каждого значения в массив неотрицательных целых чисел. Возвращает массив, где индекс соответствует числу, а значение по этому индексу — количеству раз, которое это число встречается в исходном массиве. То есть если исходный массив был таким — [0, 1, 1, 2, 2, 2, 3], numpy.bincount вернёт [1 2 3 1]. Это означает, что число 0 встречается один раз, число 1 — два раза, число 2 — три раза, число 3 — один раз.
2️⃣ Разберём задачку про игральные карты.
В целом, при таком условии у нас могут возникнуть несколько ситуаций.
▫️Первая.
Когда мы достали первый туз, он оказался пиковым, а двойка треф нам ещё не попадалась. Тогда вероятность достать пиковый туз далее окажется равна нулю, а двойку треф — единице (ведь мы точно её рано или поздно достанем).
▫️Вторая.
На момент когда мы добрались до первого туза, он не пиковый, а двойка треф уже вышла из колоды. Соответственно, вероятность встретить её дальше равна нулю, а вероятность встретить пиковый туз — единице.
▫️Третья.
Когда мы достали первый туз, он оказался пиковым, а двойка треф вышла раньше. Поэтому вероятность встретить дальше обе карты равна нулю.
▫️Четыре.
Озвученные выше три варианта при многократном повторении эксперимента дают нам одинаковые шансы на то, что следующей картой, которую мы найдём, будет как пиковый туз, так и трефовая двойка. Поэтому нас больше всего интересует ситуация, когда первый туз не пиковый и двойка треф ещё есть в колоде.
Будем считать, что мы уже вытянули n карт, включая первого туза. Так в колоде осталось (52 − n) карт. Вероятность вытянуть пикового туза тогда составляет 1 / (52 − n). То же самое происходит с трефовой двойкой — 1 / (52 − n). В результате, вероятности равны.
#разбор_задач
1️⃣ Метод numpy.bincount используется для подсчёта количества вхождений каждого значения в массив неотрицательных целых чисел. Возвращает массив, где индекс соответствует числу, а значение по этому индексу — количеству раз, которое это число встречается в исходном массиве. То есть если исходный массив был таким — [0, 1, 1, 2, 2, 2, 3], numpy.bincount вернёт [1 2 3 1]. Это означает, что число 0 встречается один раз, число 1 — два раза, число 2 — три раза, число 3 — один раз.
2️⃣ Разберём задачку про игральные карты.
В целом, при таком условии у нас могут возникнуть несколько ситуаций.
▫️Первая.
Когда мы достали первый туз, он оказался пиковым, а двойка треф нам ещё не попадалась. Тогда вероятность достать пиковый туз далее окажется равна нулю, а двойку треф — единице (ведь мы точно её рано или поздно достанем).
▫️Вторая.
На момент когда мы добрались до первого туза, он не пиковый, а двойка треф уже вышла из колоды. Соответственно, вероятность встретить её дальше равна нулю, а вероятность встретить пиковый туз — единице.
▫️Третья.
Когда мы достали первый туз, он оказался пиковым, а двойка треф вышла раньше. Поэтому вероятность встретить дальше обе карты равна нулю.
▫️Четыре.
Озвученные выше три варианта при многократном повторении эксперимента дают нам одинаковые шансы на то, что следующей картой, которую мы найдём, будет как пиковый туз, так и трефовая двойка. Поэтому нас больше всего интересует ситуация, когда первый туз не пиковый и двойка треф ещё есть в колоде.
Будем считать, что мы уже вытянули n карт, включая первого туза. Так в колоде осталось (52 − n) карт. Вероятность вытянуть пикового туза тогда составляет 1 / (52 − n). То же самое происходит с трефовой двойкой — 1 / (52 − n). В результате, вероятности равны.
#разбор_задач
👍8❤2