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

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

Во вопросам сотрудничества: @AlexErf
Download Telegram
Вот код, который создает интерактивную визуализацию, где точки движутся, образуя различные узоры. Этот код создает окно с анимацией точек, которые перемещаются по кругу и создают интересные узоры. К тому же, это легко настраивается для других геометрических форм.


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 🤖
Давайте рассмотрим интересный пример оптимизированного кода без графики. Здесь мы попробуем найти самый длинный общий префикс среди списка строк. Это задача с большими списками строк, которую можно значительно ускорить, оптимизировав подход.

❗️Популярная задача на собеседованиях 👆

### 1. Наивное решение

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

### 2. Оптимизированное решение: Используем zip и itertools

С помощью zip и itertools.takewhile можно написать более компактный и быстрый вариант решения, где мы проходим по символам сразу в каждой строке:


from itertools import takewhile

def longest_common_prefix(strings):
if not strings:
return ""
# Проверяем символы по позициям, пока все строки имеют одинаковый символ в одной позиции
prefix = ''.join(
c[0] for c in takewhile(lambda x: len(set(x)) == 1, zip(*strings))
)
return prefix

# Пример использования
strings = ["optimization", "optimize", "option", "optimum"]
print("Самый длинный общий префикс:", longest_common_prefix(strings))


### Объяснение кода:
1. `zip(*strings)` — объединяет символы по одной позиции из каждой строки в кортежи. Например, для ["optimization", "optimize", "option", "optimum"] получится ('o', 'o', 'o', 'o') для первой позиции.
2. `takewhile(lambda x: len(set(x)) == 1, ...)` — проходит по символам, пока в каждой позиции у всех строк одинаковый символ.
3. Компоновка результата — только нужные символы сохраняются, и ''.join() собирает их в строку.

### Почему это быстрее?
- Использование zip и itertools позволяет обрабатывать каждый символ только один раз, без дополнительных проверок по индексам, что ускоряет процесс для длинных строк или больших списков.
- Алгоритм оптимален по времени и памяти, так как завершается, как только находит первое различие между строками.

Подпишись 👉🏻 @KodduuPython 🤖
👍3
Отпечатки пальцев, в контексте программирования, могут использоваться для уникальной идентификации данных, обычно с помощью хеширования. Чтобы продемонстрировать, как это работает, можно использовать хеш-функции, например, SHA-256 из библиотеки hashlib в Python. В примере ниже создадим отпечаток пальца для строки, чтобы показать, как хеширование создает уникальный идентификатор для входных данных.

Вот пример кода:


import hashlib

# Функция для создания отпечатка пальца (хеш) данных
def create_fingerprint(data: str) -> str:
# Преобразуем строку в байты
byte_data = data.encode('utf-8')
# Создаем хеш с использованием алгоритма SHA-256
fingerprint = hashlib.sha256(byte_data).hexdigest()
return fingerprint

# Примеры данных
data1 = "Hello, world!"
data2 = "Hello, world!"
data3 = "Goodbye, world!"

# Создаем отпечатки пальцев для каждого из примеров
fingerprint1 = create_fingerprint(data1)
fingerprint2 = create_fingerprint(data2)
fingerprint3 = create_fingerprint(data3)

# Выводим результаты
print(f"Отпечаток пальца для 'Hello, world!': {fingerprint1}")
print(f"Отпечаток пальца для идентичной строки 'Hello, world!': {fingerprint2}")
print(f"Отпечаток пальца для 'Goodbye, world!': {fingerprint3}")

# Проверка уникальности
print("\nОтпечатки идентичны для одинаковых данных?" , fingerprint1 == fingerprint2)
print("Отпечатки различаются для разных данных?", fingerprint1 != fingerprint3)


### Объяснение кода:
1. Хеширование данных: Функция create_fingerprint принимает строку и создает для нее хеш с помощью алгоритма SHA-256, возвращая строку с шестнадцатеричным представлением хеша.
2. Проверка идентичности: Отпечатки пальцев для одинаковых данных идентичны, но если изменить хотя бы один символ, хеш будет совершенно другим, что демонстрирует чувствительность хеша к изменениям в данных.

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

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

PyFingerprint — это библиотека Python, которая позволяет управлять биометрическими датчиками отпечатков пальцев на базе модуля ZFM-20. Она подходит для простых приложений и работает с популярными USB-сканерами, предоставляя базовый набор функций, включая регистрацию, поиск и удаление отпечатков.

#### Установка
PyFingerprint можно установить через pip:

pip install PyFingerprint


#### Пример кода
Следующий код показывает, как инициализировать сканер и зарегистрировать или идентифицировать отпечаток пальца:


from pyfingerprint.pyfingerprint import PyFingerprint

try:
# Подключение к сканеру отпечатков пальцев
f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000)
if not f.verifyPassword():
raise ValueError("Пароль не подходит!")

# Ожидание отпечатка пальца
print("Поместите палец на сканер...")
while not f.readImage():
pass

# Конвертация изображения отпечатка в шаблон
f.convertImage(0x01)
positionNumber = f.searchTemplate()
if positionNumber >= 0:
print(f"Отпечаток найден на позиции #{positionNumber}")
else:
print("Отпечаток не распознан")

except Exception as e:
print("Ошибка:", str(e))


#### Преимущества и ограничения
* Преимущества: Легкость в использовании, простота интеграции с недорогими USB-сканерами.
* Ограничения: Подходит только для датчиков серии ZFM, ограниченный набор функций для базовых приложений.

PyFingerprint — отличный вариант для проектов с бюджетными ограничениями, особенно для простых DIY-проектов с использованием Raspberry Pi или Arduino.

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

Предположим, что у нас есть простое изображение отпечатка пальца (в реальности снимок делается датчиком отпечатков и обрабатывается специализированной библиотекой). Вместо изображения будем работать с данными в формате координат уникальных точек, таких как минуции.


# Пример извлеченных данных для отпечатка пальца
# Координаты минуций и углы наклона (в реальных случаях извлекаются автоматически)
fingerprint_data_1 = [
{"x": 100, "y": 200, "angle": 45},
{"x": 120, "y": 215, "angle": 60},
{"x": 130, "y": 210, "angle": 90},
{"x": 115, "y": 205, "angle": 30},
]

# Для второго отпечатка (моделируем тот же отпечаток с небольшой погрешностью)
fingerprint_data_2 = [
{"x": 101, "y": 199, "angle": 47},
{"x": 119, "y": 216, "angle": 59},
{"x": 132, "y": 211, "angle": 88},
{"x": 116, "y": 206, "angle": 32},
]


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

#### Функция для генерации шаблона

import math

# Функция для создания шаблона отпечатка
def create_fingerprint_template(fingerprint_data):
# Преобразуем каждую минутию в формат (x, y, angle)
template = []
for minutia in fingerprint_data:
template.append((minutia["x"], minutia["y"], minutia["angle"]))
return template

# Создаем шаблоны для двух отпечатков
template_1 = create_fingerprint_template(fingerprint_data_1)
template_2 = create_fingerprint_template(fingerprint_data_2)


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

#### Функция для сравнения

# Задаем допустимые отклонения для сравнения
tolerance_position = 5 # Допустимое отклонение в координатах
tolerance_angle = 5 # Допустимое отклонение в углах

# Функция сравнения двух шаблонов
def compare_fingerprint_templates(template1, template2):
matches = 0
for minutia1 in template1:
for minutia2 in template2:
# Проверяем, что координаты и угол находятся в пределах допустимых отклонений
if (abs(minutia1[0] - minutia2[0]) <= tolerance_position and
abs(minutia1[1] - minutia2[1]) <= tolerance_position and
abs(minutia1[2] - minutia2[2]) <= tolerance_angle):
matches += 1
break # Переходим к следующей точке
# Возвращаем количество совпавших точек
return matches

# Сравниваем два шаблона
matches = compare_fingerprint_templates(template_1, template_2)
total_points = min(len(template_1), len(template_2))
similarity = matches / total_points

print(f"Совпавшие точки: {matches} из {total_points}")
print(f"Сходство: {similarity:.2f}")


### Вывод
Код выше покажет количество совпавших точек и степень сходства в процентном выражении (0.0 - 1.0). Чем ближе значение к 1.0, тем больше вероятность того, что отпечатки принадлежат одному человеку.

### Объяснение работы кода
1. Допуски: Мы задали допустимые отклонения в 5 единиц по координатам и углу, чтобы допустить незначительные отличия из-за положения пальца.
2. Совпадение точек: Мы проходим по каждому элементу из первого шаблона и проверяем, есть ли совпадение в пределах допустимого отклонения в данных второго шаблона. Если найдена подходящая точка, добавляем совпадение.
3. Подсчет сходства: Общее количество совпавших точек делится на минимальное количество точек между двумя шаблонами, чтобы получить процент совпадения.

Подпишись 👉🏻 @KodduuPython 🤖
👍1
В наше время анализ социальных сетей и построение рекомендаций стали важными задачами для платформ, взаимодействующих с пользователями. Библиотека `networkx` позволяет моделировать такие системы с помощью графов, где узлы представляют пользователей, а рёбра — связи между ними. С networkx можно выявлять влиятельных пользователей, находить кластеры и строить алгоритмы рекомендаций.

### Установка

Установить networkx можно с помощью pip:

pip install networkx


### Пример: Моделирование Социальной Сети

Представим, что у нас есть небольшая социальная сеть, где пользователи связаны друг с другом через дружеские или профессиональные связи. Мы построим граф, где узлы — это пользователи, а рёбра — связи между ними.


import networkx as nx
import matplotlib.pyplot as plt

# Создаем граф
G = nx.Graph()

# Добавляем узлы (пользователей) и связи между ними
connections = [
("Alice", "Bob"),
("Alice", "Charlie"),
("Bob", "David"),
("Charlie", "David"),
("David", "Eve"),
("Eve", "Frank"),
("Frank", "Alice"),
("Charlie", "Eve"),
]
G.add_edges_from(connections)

# Визуализация сети
plt.figure(figsize=(8, 6))
nx.draw(G, with_labels=True, node_color='lightblue', node_size=2000, font_size=15)
plt.title("Социальная сеть пользователей")
plt.show()


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

Подпишись 👉🏻 @KodduuPython 🤖
Граф, визуализирующий отношения между пользователями.

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


# Вычисляем степень центральности для каждого узла
centrality = nx.degree_centrality(G)
print("Центральность пользователей:")
for user, central_value in centrality.items():
print(f"{user}: {central_value:.2f}")


Рекомендательные системы используют графы для поиска пользователей, которых стоит порекомендовать друг другу. Один из простых методов — использовать алгоритм общих друзей. Он предлагает пользователю новых друзей на основе количества общих знакомых с другими.

#### Функция для поиска рекомендаций

def recommend_friends(G, user):
# Для каждого узла считаем общих друзей, которые не связаны с текущим пользователем
potential_friends = {}
for friend in G.neighbors(user):
for friend_of_friend in G.neighbors(friend):
if friend_of_friend != user and not G.has_edge(user, friend_of_friend):
if friend_of_friend in potential_friends:
potential_friends[friend_of_friend] += 1
else:
potential_friends[friend_of_friend] = 1

# Сортируем по количеству общих друзей и возвращаем рекомендации
recommendations = sorted(potential_friends.items(), key=lambda x: x[1], reverse=True)
return [user for user, _ in recommendations]

# Рекомендуем друзей для пользователя "Alice"
recommended_friends = recommend_friends(G, "Alice")
print("Рекомендации для Alice:", recommended_friends)


Этот алгоритм выведет список пользователей, которых стоит порекомендовать Alice как потенциальных друзей, на основе общих связей. Например, если у Alice и David есть общие друзья, то David станет для нее рекомендуемым контактом.

### Применение: Поиск Кластеров (Групп)

Социальные сети часто образуют кластеры — группы людей с тесными связями внутри группы и меньшим количеством связей с пользователями за пределами группы. В networkx можно найти такие кластеры с помощью алгоритма связных компонент или более сложных алгоритмов, таких как Girvan-Newman.


# Используем связные компоненты для поиска групп в сети
clusters = list(nx.connected_components(G))
print("Кластеры пользователей в сети:", clusters)


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

### Расширенное Применение: Поиск путей для рекомендаций

Рекомендательные алгоритмы также могут использовать алгоритм кратчайших путей. Например, если у пользователя есть связь с кем-то через промежуточного друга, эта цепочка может стать рекомендацией для создания новых контактов.


# Ищем кратчайший путь между двумя пользователями
path = nx.shortest_path(G, source="Alice", target="Frank")
print("Кратчайший путь между Alice и Frank:", path)


Если между двумя пользователями можно найти путь, их можно рекомендовать друг другу, как потенциальных друзей на основе "косвенной связи".

### Заключение

Библиотека networkx предоставляет удобные инструменты для анализа и моделирования социальных сетей и создания алгоритмов рекомендаций. Она позволяет быстро выявить влиятельных пользователей, рекомендовать новых друзей, находить кластеры и анализировать косвенные связи. С помощью этой библиотеки можно легко создавать простые модели социальных сетей и закладывать основу для сложных рекомендательных систем, применяемых на реальных платформах.

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