Kodduu Python
1.08K subscribers
311 photos
28 videos
186 links
Научись программировать на Python на интересных примерах

Самый быстрый курс https://stepik.org/a/187914
Самый нескучный курс https://stepik.org/a/185238

Во вопросам сотрудничества: @AlexErf
Download Telegram
Давайте создадим сложную программу на Python без использования ООП. Мы реализуем алгоритм Быстрого преобразования Фурье (FFT) и применим его для анализа звукового сигнала. Также визуализируем результаты с помощью matplotlib.


import numpy as np
import matplotlib.pyplot as plt
import wave
import sys

# Чтение звукового файла
def read_wave(filename):
with wave.open(filename, 'r') as wf:
n_frames = wf.getnframes()
frames = wf.readframes(n_frames)
signal = np.frombuffer(frames, dtype=np.int16)
framerate = wf.getframerate()
return signal, framerate

# Реализация алгоритма FFT
def fft(signal):
N = len(signal)
if N <= 1:
return signal
even = fft(signal[::2])
odd = fft(signal[1::2])
T = [np.exp(-2j * np.pi * k / N) * odd[k % (N//2)] for k in range(N//2)]
return [even[k] + T[k] for k in range(N//2)] + \
[even[k] - T[k] for k in range(N//2)]

# Пример использования
if __name__ == "__main__":
# Проверка аргументов командной строки
if len(sys.argv) < 2:
print("Использование: python fft.py <filename.wav>")
sys.exit(1)

filename = sys.argv[1]
signal, framerate = read_wave(filename)
N = 1024 # Размер выборки

# Обрезаем или дополняем сигнал до нужного размера
if len(signal) < N:
signal = np.pad(signal, (0, N - len(signal)), 'constant')
else:
signal = signal[:N]

# Выполняем FFT
spectrum = fft(signal)

# Получаем частоты
freqs = np.fft.fftfreq(N, d=1/framerate)

# Визуализация
plt.figure(figsize=(12, 6))

plt.subplot(121)
plt.plot(np.arange(N), signal)
plt.title('Временная область')
plt.xlabel('Образцы')
plt.ylabel('Амплитуда')

plt.subplot(122)
plt.plot(freqs[:N//2], np.abs(spectrum[:N//2]) * 2 / N)
plt.title('Частотная область')
plt.xlabel('Частота (Гц)')
plt.ylabel('Амплитуда')

plt.tight_layout()
plt.show()


Описание кода:

1. Импортируем необходимые модули:
- numpy для работы с массивами и математическими операциями.
- matplotlib.pyplot для визуализации.
- wave для работы с WAV-файлами.
- sys для доступа к аргументам командной строки.

2. Функция `read_wave`:
- Читает WAV-файл и возвращает сигнал и частоту дискретизации.

3. Функция `fft`:
- Рекурсивная реализация алгоритма Быстрого преобразования Фурье.
- Разделяет сигнал на четные и нечетные части и рекурсивно вычисляет их преобразования.
- Использует формулу "бабочки" для комбинирования результатов.

4. Основная часть программы:
- Проверяет наличие аргумента командной строки (имя файла).
- Читает звуковой сигнал из файла.
- Обрезает или дополняет сигнал до размера N (1024 образца).
- Выполняет FFT и получает спектр сигнала.
- Вычисляет частоты, соответствующие каждому значению спектра.
- Визуализирует исходный сигнал и его спектр.

5. Визуализация:
- Первая графика показывает сигнал во временной области.
- Вторая графика показывает амплитудный спектр сигнала в частотной области.

Как использовать:

1. Подготовьте WAV-файл:
- Убедитесь, что у вас есть звуковой файл в формате WAV для анализа.

2. Запустите скрипт:
- В командной строке выполните:

python fft.py your_audio_file.wav

- Замените your_audio_file.wav на имя вашего файла.

3. Просмотрите результаты:
- Появится окно с двумя графиками, отображающими сигнал и его спектр.

Примечания:

- Размер выборки `N`:
- Выбранное значение N = 1024 обеспечивает баланс между разрешением по времени и частоте.
- Можно изменить N в коде для анализа большего или меньшего фрагмента сигнала.

- Ограничения:
- Данная реализация FFT не оптимизирована и предназначена для образовательных целей.
- Для больших сигналов рекомендуется использовать numpy.fft.fft для производительности.

Подпишись 👉🏻 @KodduuPython 🤖
🎉1
Собрали программу для тех кому некогда, но нужно быстро пройти весь Python + DataScience 👈👈👈

Подпишись 👉🏻 @KodduuPython 🤖
4🔥1
Создадим интересную программу на Python, которая реализует генетический алгоритм для решения задачи оптимизации — нахождения минимума функции. Мы применим генетический алгоритм для минимизации функции Растригина, известной своей сложностью и множеством локальных минимумов.


import numpy as np
import matplotlib.pyplot as plt

# Определение функции Растригина
def rastrigin(x):
A = 10
return A * len(x) + sum([(xi**2 - A * np.cos(2 * np.pi * xi)) for xi in x])

# Параметры генетического алгоритма
POP_SIZE = 100 # Размер популяции
GENES = 2 # Количество генов (размерность задачи)
GENERATIONS = 50 # Количество поколений
MUTATION_RATE = 0.1 # Вероятность мутации

# Инициализация популяции
population = [np.random.uniform(-5.12, 5.12, GENES) for _ in range(POP_SIZE)]

# Эволюционный цикл
best_scores = []
for generation in range(GENERATIONS):
# Оценка приспособленности
fitness = [ -rastrigin(individual) for individual in population]

# Сохранение лучшего результата
best_scores.append(-min(fitness))

# Селекция
parents = [population[i] for i in np.argsort(fitness)[-POP_SIZE//2:]]

# Кроссовер
offspring = []
for _ in range(POP_SIZE//2):
parent1, parent2 = np.random.choice(parents, 2, replace=False)
crossover_point = np.random.randint(1, GENES)
child = np.concatenate([parent1[:crossover_point], parent2[crossover_point:]])
offspring.append(child)

# Мутация
for individual in offspring:
if np.random.rand() < MUTATION_RATE:
mutation_point = np.random.randint(GENES)
individual[mutation_point] += np.random.uniform(-1, 1)
individual[mutation_point] = np.clip(individual[mutation_point], -5.12, 5.12)

# Обновление популяции
population = parents + offspring

# Вывод результатов
best_individual = population[np.argmax(fitness)]
print("Лучшее решение:", best_individual)
print("Значение функции:", rastrigin(best_individual))

# Визуализация сходимости
plt.plot(best_scores)
plt.title('Сходимость генетического алгоритма')
plt.xlabel('Поколение')
plt.ylabel('Значение функции')
plt.show()


Описание кода:

1. Функция Растригина (`rastrigin`): сложная функция с множеством локальных минимумов, часто используемая для тестирования алгоритмов оптимизации.

2. Параметры алгоритма:
- POP_SIZE: количество особей в популяции.
- GENES: количество генов в хромосоме (размерность задачи).
- GENERATIONS: количество поколений для эволюции.
- MUTATION_RATE: вероятность мутации потомка.

3. Инициализация популяции: создаем начальную популяцию со случайными значениями в диапазоне [-5.12, 5.12].

4. Эволюционный цикл:
- Оценка приспособленности: вычисляем отрицательное значение функции Растригина для каждой особи (так как мы минимизируем функцию).
- Сохранение лучшего результата: отслеживаем наилучшее значение функции в каждом поколении.
- Селекция: выбираем лучших особей (с наилучшей приспособленностью) для создания потомства.
- Кроссовер: комбинируем гены пар родителей для создания новых особей.
- Мутация: вносим случайные изменения в гены потомков с определенной вероятностью.
- Обновление популяции: формируем новую популяцию из родителей и потомков.

5. Вывод результатов:
- Находим и выводим лучшую особь после всех поколений.
- Выводим соответствующее значение функции Растригина.
- Строим график сходимости значений функции по поколениям.

Как запустить код:

1. Установите необходимые библиотеки:


pip install numpy matplotlib


2. Сохраните код в файл, например `genetic_algorithm.py`.

3. Запустите скрипт:


python genetic_algorithm.py


Ожидаемый результат:

- В консоли отобразится лучшее найденное решение и значение функции в этой точке.
- Откроется график, показывающий, как значение функции менялось по мере эволюции поколений.

Примечания:
2
- Эксперименты с параметрами: Попробуйте изменить параметры алгоритма (размер популяции, количество поколений, вероятность мутации), чтобы увидеть, как они влияют на результат и скорость сходимости.
- Расширение на большую размерность: Вы можете увеличить GENES для решения задачи в пространстве большей размерности, что сделает задачу более сложной.

Заключение:

Этот пример демонстрирует применение генетических алгоритмов для решения задач оптимизации сложных функций. Генетические алгоритмы имитируют процессы естественного отбора и генетической мутации, позволяя находить приближенные решения в задачах, где аналитическое решение затруднительно.

Подпишись 👉🏻 @KodduuPython 🤖
🔥2
Вот код, который создает интерактивную визуализацию, где точки движутся, образуя различные узоры. Этот код создает окно с анимацией точек, которые перемещаются по кругу и создают интересные узоры. К тому же, это легко настраивается для других геометрических форм.


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# Настройка параметров
num_points = 50
radius = 10

# Создаем исходные координаты точек на окружности
angles = np.linspace(0, 2 * np.pi, num_points, endpoint=False)
x_coords = radius * np.cos(angles)
y_coords = radius * np.sin(angles)

fig, ax = plt.subplots()
ax.set_aspect('equal', 'box')
scatter = ax.scatter(x_coords, y_coords, s=50, color='blue')
ax.set_xlim(-radius * 1.2, radius * 1.2)
ax.set_ylim(-radius * 1.2, radius * 1.2)

def update(frame):
# Обновление углов и координат для движения точек
new_angles = angles + 0.1 * frame
x_coords = radius * np.cos(new_angles + frame * 0.01)
y_coords = radius * np.sin(new_angles + frame * 0.01)
scatter.set_offsets(np.c_[x_coords, y_coords])
return scatter,

ani = animation.FuncAnimation(fig, update, frames=200, interval=50, blit=True)
plt.show()


Этот код:

- Создает 50 точек, которые расположены по кругу.
- С каждой итерацией они слегка смещаются, создавая эффект "волны" и "размытости".
- Получается гипнотическая анимация, которую можно менять, изменяя радиус, количество точек или скорость.

Подпишись 👉🏻 @KodduuPython 🤖
Попробуем создать более сложную анимацию, в которой точки будут двигаться по нелинейным траекториям, создавая узоры. Этот пример использует траектории, которые зависят от синусоидальных и косинусоидальных функций с переменным радиусом, чтобы добавить нелинейные колебания.


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# Настройка параметров
num_points = 50
base_radius = 10

# Создаем исходные углы для точек
angles = np.linspace(0, 2 * np.pi, num_points, endpoint=False)

fig, ax = plt.subplots()
ax.set_aspect('equal', 'box')
scatter = ax.scatter([], [], s=50, color='purple')
ax.set_xlim(-base_radius * 1.5, base_radius * 1.5)
ax.set_ylim(-base_radius * 1.5, base_radius * 1.5)

# Обновление координат для нелинейных траекторий
def update(frame):
# Нелинейный радиус с добавлением синусоидальной амплитуды
radius = base_radius + 3 * np.sin(frame * 0.05)
x_coords = radius * np.cos(angles + 0.05 * frame) + 2 * np.sin(angles * 3 + frame * 0.1)
y_coords = radius * np.sin(angles + 0.05 * frame) + 2 * np.cos(angles * 4 + frame * 0.1)

scatter.set_offsets(np.c_[x_coords, y_coords])
return scatter,

# Настройка анимации
ani = animation.FuncAnimation(fig, update, frames=400, interval=50, blit=True)
plt.show()


### Как это работает:
- Радиус каждой точки зависит от времени и изменяется по синусоиде, что делает движение точек более динамичным.
- Траектория движения каждой точки - это комбинация нескольких синусоидальных и косинусоидальных функций, что создает уникальные узоры на каждом кадре.
- Частотные множители для angles (например, 3 и 4 внутри x_coords и `y_coords`) добавляют колебания по окружности, что создает сложные, закрученные траектории.

Подпишись 👉🏻 @KodduuPython 🤖
This media is not supported in your browser
VIEW IN TELEGRAM
Код анимации выше 👆👆👆

Подпишись 👉🏻 @KodduuPython 🤖
👍3
Собрали программу Junior FullStack Developer and Data Scientist, включает 3 наших самых компактных курса, можно пройти за 2-3 викэнда. В программе вся база по Python + вся база по JavaScript + вся база по Data Science в Python 😎

Подпишись 👉🏻 @KodduuPython 🤖
Как насчёт кода, который рисует фрактал *Множества Мандельброта* и анимирует его приближение? Это отличный пример красоты и сложности фрактальной геометрии! И демо того как оно может тормозить на большом кол-во объектов 🐌 В следующем посте расскажем как ускорить ⚡️

Вот код для визуализации этого фрактала с постепенным "увеличением" на определённой области:


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# Настройка параметров фрактала
width, height = 800, 800 # Размер окна
max_iter = 256 # Максимальное количество итераций

# Начальные координаты для анимации (центр Мандельброта)
xmin, xmax, ymin, ymax = -2.0, 1.0, -1.5, 1.5

# Функция для вычисления множества Мандельброта
def mandelbrot(c, max_iter):
z = c
for n in range(max_iter):
if abs(z) > 2:
return n
z = z*z + c
return max_iter

# Функция, которая генерирует фрактал
def generate_mandelbrot(xmin, xmax, ymin, ymax, width, height, max_iter):
x, y = np.linspace(xmin, xmax, width), np.linspace(ymin, ymax, height)
C = x + y[:, None] * 1j
mandelbrot_set = np.frompyfunc(lambda c: mandelbrot(c, max_iter), 1, 1)(C).astype(np.float32)
return mandelbrot_set

# Создаем фигуру и ось для анимации
fig, ax = plt.subplots(figsize=(6, 6))
im = ax.imshow(generate_mandelbrot(xmin, xmax, ymin, ymax, width, height, max_iter),
extent=(xmin, xmax, ymin, ymax), cmap='hot', origin='lower')

# Функция обновления для анимации
def update(frame):
zoom_factor = 1.5 ** (-frame * 0.1)
x_center, y_center = -0.7435, 0.1314 # координаты интересной точки
dx, dy = (xmax - xmin) * zoom_factor, (ymax - ymin) * zoom_factor
xmin_new, xmax_new = x_center - dx / 2, x_center + dx / 2
ymin_new, ymax_new = y_center - dy / 2, y_center + dy / 2

mandelbrot_set = generate_mandelbrot(xmin_new, xmax_new, ymin_new, ymax_new, width, height, max_iter)
im.set_data(mandelbrot_set)
im.set_extent((xmin_new, xmax_new, ymin_new, ymax_new))
return im,

# Анимация фрактала
ani = animation.FuncAnimation(fig, update, frames=100, interval=50, blit=True)
plt.show()


### Объяснение кода:
- Множество Мандельброта создаётся путём проверки, стремятся ли точки в комплексной плоскости к бесконечности при итерациях по формуле \( z = z^2 + c \).
- Функция `generate_mandelbrot` вычисляет фрактал для заданных границ и преобразует его в массив значений.
- Анимация `update` постепенно уменьшает масштаб (приближает) вокруг интересной точки, что позволяет видеть больше деталей.

Подпишись 👉🏻 @KodduuPython 🤖
This media is not supported in your browser
VIEW IN TELEGRAM
Код анимации тут 👆👆👆

Подпишись 👉🏻 @KodduuPython 🤖
Для ускорения анимации Множества Мандельброта можно воспользоваться несколькими подходами:

1. Уменьшить разрешение (размер width и `height`), чтобы уменьшить количество вычисляемых точек.
2. Оптимизировать функцию `mandelbrot` с использованием Numba для компиляции в машинный код, что значительно ускоряет обработку.
3. Параллельные вычисления для обработки точек массива.

Давайте применим Numba и создадим ускоренную версию. Для этого сначала нужно установить numba, если она не установлена:


pip install numba


Затем добавим @njit из Numba, чтобы ускорить расчёты:


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from numba import njit

# Настройка параметров фрактала
width, height = 600, 600 # Уменьшили размер для повышения скорости
max_iter = 256 # Максимальное количество итераций

# Компилируем функцию с помощью Numba
@njit
def mandelbrot(c, max_iter):
z = c
for n in range(max_iter):
if abs(z) > 2:
return n
z = z * z + c
return max_iter

@njit
def generate_mandelbrot(xmin, xmax, ymin, ymax, width, height, max_iter):
x = np.linspace(xmin, xmax, width)
y = np.linspace(ymin, ymax, height)
mandelbrot_set = np.empty((height, width), dtype=np.float32)
for i in range(width):
for j in range(height):
mandelbrot_set[j, i] = mandelbrot(x[i] + 1j * y[j], max_iter)
return mandelbrot_set

# Создаем фигуру и ось для анимации
fig, ax = plt.subplots(figsize=(6, 6))
im = ax.imshow(generate_mandelbrot(-2.0, 1.0, -1.5, 1.5, width, height, max_iter),
extent=(-2.0, 1.0, -1.5, 1.5), cmap='hot', origin='lower')

# Функция обновления для анимации
def update(frame):
zoom_factor = 1.5 ** (-frame * 0.1)
x_center, y_center = -0.7435, 0.1314 # координаты интересной точки
dx, dy = (1.0 - -2.0) * zoom_factor, (1.5 - -1.5) * zoom_factor
xmin_new, xmax_new = x_center - dx / 2, x_center + dx / 2
ymin_new, ymax_new = y_center - dy / 2, y_center + dy / 2

mandelbrot_set = generate_mandelbrot(xmin_new, xmax_new, ymin_new, ymax_new, width, height, max_iter)
im.set_data(mandelbrot_set)
im.set_extent((xmin_new, xmax_new, ymin_new, ymax_new))
return im,

# Анимация фрактала
ani = animation.FuncAnimation(fig, update, frames=100, interval=50, blit=True)
plt.show()


### Изменения в коде:
- Numba (`@njit`) значительно ускоряет функции mandelbrot и generate_mandelbrot за счёт компиляции в машинный код.
- Уменьшение `width` и `height` до 600x600 пикселей снижает нагрузку на процессор.

Эти изменения помогут повысить производительность, делая анимацию более плавной и быстрой.

Подпишись 👉🏻 @KodduuPython 🤖
This media is not supported in your browser
VIEW IN TELEGRAM
Код анимации тут 👆👆👆

Подпишись 👉🏻 @KodduuPython 🤖
Скидка на программу Junior FullStack Developer and Data Scientist действует до 22.11.

Программа включает 3 наших самых компактных курса, можно пройти за 2-3 викэнда. В программе вся база по Python + вся база по JavaScript + вся база по Data Science в Python 😎

Подпишись 👉🏻 @KodduuPython 🤖