Вы решили изучить глубокое обучение, изучили некоторую теорию и теперь хотите заняться практической практикой, но перед вами стоит дилемма, с какой среды начать (Tensorflow или PyTorch)?

Не волнуйтесь, я тоже был там, и именно поэтому я начинаю с этой последовательности, где я буду писать серию статей, которые помогут вам начать работу с PyTorch!

Итак, приступим!

Ход статьи:

  • Краткое введение в PyTorch
  • Тензоры
  • Инициализация тензора
  • Атрибуты тензоров
  • Операции над тензорами
  • Совместимость PyTorch-NumPy
  • Совместимость с графическим/процессорным процессором

Что такое PyTorch?

PyTorch — это платформа машинного обучения с открытым исходным кодом, основанная на библиотеке Torch, используемая для таких приложений, как компьютерное зрение и обработка естественного языка, в первую очередь разработанная исследовательской лабораторией искусственного интеллекта Facebook (теперь Meta). Это обеспечивает максимальную гибкость и скорость научных вычислений для глубокого обучения. Кроме того, это замена NumPy для использования мощности графических процессоров.

Почему PyTorch?

Согласно моим исследованиям, TensorFlow, Keras и PyTorch — самые популярные библиотеки, упомянутые в сообществе машинного обучения. Tensorflow хорошо подходит, если вы хотите разрабатывать модели для производства, разрабатывать модели, которые необходимо развернуть на мобильных платформах, и вам необходимо использовать крупномасштабное распределенное обучение моделей.

Принимая во внимание, что PyTorch хорошо работает для исследовательских целей и если вы хотите все Pythonic (как я😉)!

Тензоры

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

Например, 1d-тензор — это вектор, 2d-тензор — это матрица, 3d-тензор — это куб, а 4d-тензор — это вектор кубов.

Если вы хотите понять это визуально, вот потрясающее видео на Youtube, в котором Даниэль Флейш, профессор кафедры физики Виттенбергского университета, фантастически объяснил это.

Инициализация тензора:

Давайте посмотрим, как создать тензор в PyTorch. Тензоры могут быть инициализированы различными способами.

Импортируем необходимые библиотеки:

import torch
import numpy as np
  1. Непосредственно из данных:
data = [[1, 2],[3, 4]]
tensor_data = torch.tensor(data)
# Example:
print(tensor_data)
# Output:
tensor([[1, 2],
        [3, 4]])

2. Создайте тензор со случайными значениями:

random_tensor = torch.Tensor(n,m)   # where n is the number of rows                 
and m is the number of columns (n x m)
# Example:
random_tensor = torch.Tensor(2,3)
print(random_tensor)
# Output:
tensor([[6.8664e-44, 7.7071e-44, 1.1771e-43],
        [6.7262e-44, 7.9874e-44, 8.1275e-44]])

3. Создайте тензор со случайными значениями между a и b:

uniform_tensor = torch.Tensor(n, m).uniform_(a, b)   # where a and b are any natural numbers
# Example:
uniform_tensor = torch.Tensor(3,3).uniform_(1,5)
print(uniform_tensor)
# Output:
tensor([[2.2433, 3.1906, 4.2577],
        [3.6101, 1.9020, 2.6306],
        [1.2986, 3.6643, 1.4555]])

4. Создайте тензор, заполненный случайными числами из равномерного распределения на интервале [0, 1):

rand_tensor = torch.rand(n, m)
# Example:
rand_tensor = torch.rand(3, 3)
print(rand_tensor)
# Output:
tensor([[0.6445, 0.5295, 0.8926],
        [0.6845, 0.2812, 0.7323],
        [0.9651, 0.4299, 0.8283]])

5. Создайте тензор нулей размером n x m:

zero_tensor = torch.zeros(n, m)
# Example:
zero_tensor = torch.zeros(3, 3)
print(zero_tensor)
# Output:
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])

6. Создайте тензор единиц размером n x m:

ones_tensor = torch.ones(n, m)

# Example:
ones_tensor = torch.ones(3, 3)
print(ones_tensor)
# Output:
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])

Атрибуты тензора:

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

tensor = torch.randn(n, m)
print("Shape of a tensor: {}".format(tensor.shape))
print("Data type of a tensor: {}".format(tensor.dtype))
print("Dimension of a tensor: {}".format(tensor.dim()))
print("Device tensor is stored on: {}".format(tensor.device))
# Example:
tensor = torch.randn(3, 3)
print("Shape of a tensor: {}".format(tensor.shape))
print("Data type of a tensor: {}".format(tensor.dtype))
print("Dimension of a tensor: {}".format(tensor.dim()))
print("Device tensor is stored on: {}".format(tensor.device))
# Output:
Shape of a tensor: torch.Size([3, 3])
Dimension of a tensor: 2
Data type of a tensor: torch.float32
Device tensor is stored on: cpu

Операции с тензорами:

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

  1. Операция индексирования:

Используя эту операцию, вы можете получить доступ или заменить элементы в тензоре.

tensor = torch.Tensor([[1, 2], [3, 4]])
# Replace an element at position 0,1
tensor[0][1] = 7
print(tensor)
# Output:
tensor([[1., 7.],
        [3., 4.]])
# Access an element at position 1,0
print(tensor[1][0])
print(tensor[1][0].item())    # using .item() you can access the scalar object
# Output:
tensor(3.)
3.0

2. Операция нарезки:

Используя эту операцию, вы можете получить доступ к элементам в определенном диапазоне индексов.

tensor = torch.Tensor([[1, 2], [3, 4], [5,6]])
# First element of every row
print(tensor[:,0])
# Output:
tensor([1., 3., 5.])
# Last element from every row
print(tensor[:,-1])
# Output:
tensor([2., 4., 6.])
# All elements from second row
print(tensor[1,:])
# Output:
tensor([3., 4.])
# All elements from last two rows
print(tensor[1:,:])
# Output:
tensor([[3., 4.],
        [5., 6.]])

3. Присоединение или объединение тензора:

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

tensor_1 = torch.Tensor([[1, 2], [3, 4], [5,6]])
tensor_2 = torch.Tensor([[8,9],[10,11],[12,13]])
new_tensor = torch.cat([tensor, ten2], dim=1)
print(new_tensor)
# Output:
tensor([[ 1.,  2.,  8.,  9.],
        [ 3.,  4., 10., 11.],
        [ 5.,  6., 12., 13.]])

Есть еще одна операция, похожая на объединение, известная как torch.stack.

4. Изменение формы тензора:

Используя эту операцию, вы можете изменить форму тензора до размера n x m.

tensor = torch.Tensor([[1, 2], [3, 4]])
reshaped_tensor_1 = reshape_tensor.view(1,4)
reshaped_tensor_2 = reshape_tensor.view(4,1)
print("Reshaped tensor 1: ",reshaped_tensor_1)
print("\nReshaped tensor 2: ",reshaped_tensor_2)
# Output:
Reshaped tensor 1 tensor:
([[1., 2., 3., 4.]])

Reshaped tensor 2 tensor:
([[1.],
  [2.],
  [3.],
  [4.]])

5. Транспонировать:

Вы можете выполнить операцию транспонирования тензора, используя .t() или .permute(-1, 0).

tensor = torch.Tensor([[1, 2], [3, 4], [5,6]])
print("Tensor: ",tensor)
print("\nTensor after transpose: ",tensor.t())
# Output:
Tensor:  tensor([[1., 2.],
        [3., 4.],
        [5., 6.]])

Tensor after transpose:  tensor([[1., 3., 5.],
        [2., 4., 6.]])

Транспонировать с помощью функции перестановки:

tensor = torch.Tensor([[1, 2], [3, 4], [5,6]])
print("Tensor: ",tensor)
print("\nTensor after transpose: ",tensor.permute(-1,0))
# Output:
Tensor:  
tensor([[1., 2.],
        [3., 4.],
        [5., 6.]])

Tensor after transpose:  
tensor([[1., 3., 5.],
        [2., 4., 6.]])

6. Комбинированный продукт:

Вы можете получить векторное произведение двух тензоров, используя любой из двух: tensor_1.cross(tensor_2) или torch.cross(tensor_1, tensor_2)

tensor_1 = torch.Tensor([[1, 2], [3, 4], [5,6]])
tensor_2 = torch.Tensor([[8, 9],[10, 11],[12, 13]])
cross_prod = tensor_1.cross(tensor_2)
print(cross_prod)
# Output:
tensor([[-14., -14.],
        [ 28.,  28.],
        [-14., -14.]])

7. Матричный продукт:

Выполняет матричное умножение двух тензоров. Если tensor_1 – это тензор (n×m), tensor_2 – это тензор (m×p), то на выходе будет (n×p) тензор.

tensor_1 = torch.Tensor([[1, 2, 3], [3, 5, 6], [7, 8, 9]])
tensor_2 = torch.Tensor([[10, 11, 12],[13, 14, 15],[16, 17, 18]])
# Using tensor_1.mm(tensor_2)
matrix_prod = tensor_1.mm(tensor_2)
print(matrix_prod)
# Output:
tensor([[ 84.,  90.,  96.],
        [191., 205., 219.],
        [318., 342., 366.]])

# Using torch.mm(tensor_1, tensor_2)
maxtrix_prod = torch.mm(tensor_1,tensor_2)
print(matrix_prod)
# Output:
tensor([[ 84.,  90.,  96.],
        [191., 205., 219.],
        [318., 342., 366.]])

8. Поэлементное умножение:

Эта операция выполняет поэлементное произведение двух тензоров.

tensor_1 = torch.Tensor([[1, 2, 3], [3, 5, 6], [7, 8, 9]])
tensor_2 = torch.Tensor([[10, 11, 12],[13, 14, 15],[16, 17, 18]])
product = tensor_1.mul(tensor_2)
print(product)
# Output:
tensor([[ 10.,  22.,  36.],
        [ 39.,  70.,  90.],
        [112., 136., 162.]])

9. Сумма тензора:

Эта операция возвращает сумму всех значений тензора.

tensor_1 = torch.Tensor([[10, 11, 12],[13, 14, 15],[16, 17, 18]])
agg = tensor_1.sum()
agg_item = agg.item()
print(agg_item)
# Output:
126.0

10. Операция добавления на месте:

Эта операция добавляет скалярное значение к каждому элементу тензора.

tensor_1 = torch.Tensor([[1, 2, 3], [3, 5, 6], [7, 8, 9]])
print(tensor_1)
tensor_1.add_(5)
print("\n",tensor_1)
# Output:
tensor([[1., 2., 3.],
        [3., 5., 6.],
        [7., 8., 9.]])

 tensor([[4.,  5.,  6.],
        [ 6.,  8.,  9.],
        [10., 11., 12.]])

Взаимодействие PyTorch-NumPy:

Вы можете легко преобразовать массив NumPy в тензор PyTorch и наоборот.

  1. Тензор PyTorch в массив NumPy:
t = torch.Tensor([[1, 2, 3], [3, 5, 6], [7, 8, 9]])
print("Pytorch tensor: ", t)
print("\n",type(t))
n = t.numpy()
print("\nNumpy array: ", n)
print("\n",type(n))
# Output:
Pytorch tensor:
tensor([[1., 2., 3.],
        [3., 5., 6.],
        [7., 8., 9.]])

<class 'torch.Tensor'>

Numpy array:
[[1. 2. 3.]
 [3. 5. 6.]
 [7. 8. 9.]]
<class 'numpy.ndarray'>

2. Массив NumPy в тензор PyTorch:

numpy_array = np.ones(5)  # this method creates a numpy array with all elements as 1
print(numpy_array)
print(type(numpy_array))
pytorch_tensor = torch.from_numpy(n)
print("\n",pytorch_tensor)
print(type(pytorch_tensor))
# Output:
[1. 1. 1. 1. 1.]
<class 'numpy.ndarray'>

tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
<class 'torch.Tensor'>

Совместимость с графическим/процессорным процессором:

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

tensor_1 = torch.Tensor([[1, 2, 3], [3, 5, 6], [7, 8, 9]])
tensor_2 = torch.Tensor([[10, 11, 12],[13, 14, 15],[16, 17, 18]])
if torch.cuda.is_available():
    tensor_1 = tensor_1.cuda()
    tensor_2 = tensor_2.cuda()

Это все на сегодня!

Надеюсь, вам понравилось изучение основ тензоров PyTorch. В следующем руководстве мы узнаем больше о наборах данных и загрузчиках данных в PyTorch, чтобы вы могли получать удовольствие от обработки данных с помощью PyTorch.

Расписание статей

  1. Тензоры
  2. Обработка данных с помощью PyTorch
  3. Превращает
  4. Создание модели с помощью PyTorch
  5. Автоматическое дифференцирование
  6. Цикл оптимизации
  7. Сохранение, загрузка и использование сохраненной модели

Не забудьте похлопать, если вам понравилась эта статья!😉

Пока!