Python и DataScience: изучаем возможности универсальной библиотеки Numpy



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

    Numpy — математическая библиотека для Python. Она позволяет выполнять разного рода вычисления эффективно и быстро. Она значительно расширяет функциональность Python благодаря специальным решениям, которые в ней применяются. В этой статье рассказывается о базовых возможностях Numpy, и это только первая часть; чуть позже будут опубликованы и другие. Статья для тех, кто только начинает изучать Numpy, вступая в дивный мир математики в Python.

    Skillbox рекомендует: Практический курс «Python-разработчик с нуля».
    Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».

    Импорт библиотеки


    import numpy as np

    В этом месте мы говорим Python, что np — это референс для Numpy, который и будет использоваться впредь.

    Теперь создадим массив python и массив np.

    # python array
    a = [1,2,3,4,5,6,7,8,9]
     
    # numpy array
    A = np.array([1,2,3,4,5,6,7,8,9])

    Большой разницы при выводе нет.

    print(a)
    print(A)
    ====================================================================
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    [1 2 3 4 5 6 7 8 9]

    Хорошо, почему в таком случае лучше использовать массив numpy вместо обычного? Ответ — потому что np позволит нам быстрее производить вычисления и модифицировать общую архитектуру приложения.

    np.arange()


    np.arange(0,10,2)
    ====================================================================
    array([0, 2, 4, 6, 8])

    ([start],stop,[step]) упорядочивает цифры. Вот что это означает для машины.

    Формируем np-список, начиная с 0 до 10, но не включаем 10, плюс увеличиваем цифры на 2 каждый раз.

    Таким образом, у нас получается вот что:
    array([0, 2, 4, 6, 8])

    Важно помнить, что последняя цифра не включается в список.

    Другой пример:

    np.arange(2,29,5)
    ====================================================================
    array([2, 7, 12, 17, 22, 27])

    Этот массив можно также назвать матрицей или вектором. Поэтому не переживайте, когда я говорю, например: «Форма матрицы — 2*3». Все это означает, что наш массив в итоге будет выглядеть примерно так:

    array([2, 7, 12],
          [17, 22, 27])

    Теперь давайте поговорим о таком параметре, как shape для массива np по умолчанию. Shape здесь — атрибут. Пример его использования — ниже.

    A = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    A.shape
    ====================================================================
    (9,)

    Это матрица из чисел, где в ряду всего 9 элементов. В принципе, идеальной является матрица 1*9, не так ли?

    В принципе, да, и для этого reshape() вступает в игру. Это метод, который изменяет размеры оригинальной матрицы так, как хотелось бы нам.

    Вот пример использования reshape() на практике.

    A = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    A.reshape(1,9)
    ====================================================================
    array([[1, 2, 3, 4, 5, 6, 7, 8, 9]])

    Обратите внимание, что reshape возвращает многомерную матрицу. На это указывают две квадратных скобки в начале. [[1, 2, 3, 4, 5, 6, 7, 8, 9]] является потенциально многомерной матрицей в отличие от [1, 2, 3, 4, 5, 6, 7, 8, 9].

    Другой пример:

    B = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    B.reshape(3,3)
    ====================================================================
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])

    Если взять параметр shape для B, то им будет (3,3):

    B.shape
    ====================================================================
    (3,3)

    Перейдем к np.zeros()


    Что прописано в этом коде?

    np.zeros((4,3))
    ====================================================================
    ???????????

    Именно: здесь задана матрица формата 3*4, заполненная нулями. Вот вывод:

    np.zeros((4,3))
    ====================================================================
    array([[0., 0., 0.],
           [0., 0., 0.],
           [0., 0., 0.],
           [0., 0., 0.]])

    np.zeros((n,m)) возвращает матрицу формата n*m, заполненную нулями. Все просто.

    А что делает np.eye()?


    Возвращает нам единичную матрицу с определенными характеристиками.

    np.eye(5)
    ====================================================================
    array([[1., 0., 0., 0., 0.],
           [0., 1., 0., 0., 0.],
           [0., 0., 1., 0., 0.],
           [0., 0., 0., 1., 0.],
           [0., 0., 0., 0., 1.]])

    Как умножить две матрицы?


    Нет проблем: для этого используется np.dot(), Эта функция — скалярное произведение, если в нее передали вектора и произведение матриц (самое обыкновенное).

    Пример: A = (2,3) & B = (3,2). Здесь число столбцов в А — 3. Число строк в В — 3. Поскольку характеристики совпадают, умножение возможно.

    # generate an identity matrix of (3 x 3)
    I = np.eye(3)
    I
    ====================================================================
    array([[1., 0., 0.],
           [0., 1., 0.],
           [0., 0., 1.]])
    
    # generate another (3 x 3) matrix to be multiplied.
    D = np.arange(1,10).reshape(3,3)
    D
    ====================================================================
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])

    Мы подготовили матрицы к умножению. Далее — действуем.

    # perform actual dot product.
    M = np.dot(D,I)
    M
    ====================================================================
    array([[1., 2., 3.],
           [4., 5., 6.],
           [7., 8., 9.]])

    А теперь давайте добавим отдельные элементы в матрицу


    # add all the elements of matrix.
    sum_val = np.sum(M)
    sum_val
    ====================================================================
    45.0

    np.sum() добавляет элементы в матрицу.

    Однако у нас есть два варианта.

    1. Складываем по строкам

    # sum along the rows
    np.sum(M,axis=1)
    ====================================================================
    array([ 6., 15., 24.])

    6 — сумма первой строки (1, 2, 3).
    15 — второй (4, 5, 6).
    24 — третьей (7, 8, 9).

    2. Складываем по столбцам

    # sum along the cols
    np.sum(M,axis=0)
    ====================================================================
    array([12., 15., 18.])

    12 — сумма по первому столбцу (1, 4, 7).
    15 — по второму (2, 5, 7).
    18 — по третьему (3, 6, 9).

    Ниже — видео, созданное автором, где все, что описано выше, объясняется еще раз, более наглядно.


    Skillbox рекомендует:

    Skillbox
    Онлайн-университет профессий будущего

    Комментарии 5

      +5
      Я бы не стал записываться на курс, к людям, которые считают что
      np.sum() добавляет элементы в матрицу.

      sum() суммирует вдоль осей
        0
        Да, суммирует вдоль осей, если добавить параметр axis (как это сделано чуть ниже).

        А вот по умолчанию, как указано в примере, эти операции применяются к массиву, как если бы он был списком чисел, вне зависимости от его формы.
        +2
        M = np.dot(D,I)

        проще использовать метод самого массива:
        M = D.dot(I)
          +1
          Для приведённых примеров тащить за собой numpy это явный overhead.
          Ибо поистине интригующие открытия Вас ждут, когда соберётесь сделать бинарник (можно с набором so/dll), независимый от интерпретатора и бибилиотек Python'а.
            0
            A = [1, 2, 3, 4, 5, 6, 7, 8, 9]
            Это матрица из чисел, где в ряду всего 9 элементов. В принципе, идеальной является матрица 1*9, не так ли?

            Вообще-то это не матрица, попробуйте ее транспонировать, например. Даже если вы ее правильно создатите
            A = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

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

            Самое читаемое