Category: Data Science

22
Мар
2020

11–12 апреля, Казань: хакатон «Интеллектуальные транспортные системы и элементы ситуационных центров»

Командам за 36 часов предстоит найти решения для задач управления «умной» транспортной инфраструктурой или развития информационно-аналитической платформы «Ситуационный центр».
— Читать дальше «Хакатон «Интеллектуальные транспортные системы и элементы с…

15
Мар
2020

Просто добавь нейросеть: 7 исторических фильмов в 4K и 60 FPS

Москва, Париж, Нью-Йорк и Англия времен Прекрасной эпохи, Луна и Марс начала космических путешествий – видео, качество которых улучшено с помощью нейросетей. Приятного просмотра!

04
Мар
2020

Хороший, плохой, злой: как Яндекс использует нейросети для борьбы со спамом и матом

Разработчики Яндекса автоматизировали борьбу со спамом и матом в своих сервисах. Рассказываем, какие инструменты они для этого использовали.

Любой сайт, где пользователи могут са…

03
Мар
2020

10 инструментов искусственного интеллекта Google, доступных каждому

Обзор десяти инструментов Google для ИИ, которые могут использовать разработчики, компании и аналитики. Где искать качественные наборы данных и как привязать к проекту готовую модель TensorFlow.

21
Фев
2020

Что умеют нейросети: 10 крутых примеров из недавних новостей

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

Мы погул…

16
Фев
2020

100+ лекций экспертов Постнауки об анализе данных, ИИ, роботах, математике и сетях

Более ста монологов российских (и не только) экспертов из 16 научных областей, связанных с информационными технологиями. Средняя длительность роликов составляет 15 мин.

Недавно …

07
Фев
2020

Как специалисту по Data Science написать классификатор, если часть данных неверно размечена

Данные важны для аналитики. Однако если они размечены неверно, от них может быть больше вреда, чем пользы. Разбираемся, как работать с такими данными.
— Читать дальше «Как специалисту по Data Science написать классификатор, если часть данных неверно ра…

04
Фев
2020

Python и динамическое программирование на примере задачи о рюкзаке

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

Момент настал – вы переезжаете в Сан-Франциско, чтобы стать известным дата сайентистом. Будете работать в крупной компании и скоро прославитесь. Но не всё сразу. Поначалу придётся ютиться в жилище, много меньшем, чем нынешний дом. Нужно решить, что взять с собой. Вы аналитик и намерены решить задачу эффективно. Обсудим алгоритм?

Описание проблемы

Представим, что на данный момент вы живёте в довольно большой квартире площадью 100 м2, а вещи занимают 50 м2. Вы знаете, что площадь нового жилья составит 40 м2 и хотите, чтобы вещи занимали не более 20 м2. Вы любите, когда на полу есть свободное место, да и не всё можно поставить впритык друг к другу. Нужно составить список вещей, определить площадь, занимаемую каждой вещью и составить рейтинг ценности предметов. Конечная цель – максимизировать материальную ценность того, что разместится на 20 квадратных метрах.

Перечисляем предметы

Вы составили список вещей и выразили занимаемую площадь в квадратных дециметрах (1 дм2 = 0.01 м2). Каждому предмету сопоставили ценность по шкале от 0 до 100. Получилась сводка данных о 29 предметах, которую можно оформить как словарь вида {'название предмета':(площадь, ценность) }:

            stuffdict = {'couch_s':(300,75), 
             'couch_b':(500,80), 
             'bed':(400,100), 
             'closet':(200,50), 
             'bed_s':(200,40), 
             'desk':(200,70), 
             'table':(300,80),
             'tv_table':(200,30),
             'armchair':(100,30),
             'bookshelf':(200,60), 
             'cabinet':(150,20),
             'game_table':(150,30),
             'hammock':(250,45),
             'diner_table_with_chairs':(250,70),
             'stools':(150,30),
             'mirror':(100,20),
             'instrument':(300,70),
             'plant_1':(25,10),
             'plant_2':(30,20),
             'plant_3':(45,25),
             'sideboard':(175,30),
             'chest_of_drawers':(25,40),
             'guest_bed':(250,40),
             'standing_lamp':(20,30), 
             'garbage_can':(30,35), 
             'bar_with_stools':(200,40), 
             'bike_stand':(100,80),
             'chest':(150,25),
             'heater':(100,25)
            }
        

Готово! Теперь видно, что кровать ('bed') занимает 400 дм2, а её ценность составляет 100, игровой стол ('game_table') занимает 150 дм2 квадратных метра и имеет ценность 30.

Максимазация ценности

Как максимизировать суммарную ценность объектов так, чтобы суммарная площадь не превышала 2000 дм2? Можно попробовать перебрать все возможные комбинации и рассчитать суммарную ценность для каждой из комбинаций. Решение получится, если выбрать максимальную суммарную ценность для 2000 дм2. Но вот незадача: и комбинаторика, и теория множеств утверждают, что 29 предметов дают 2²⁹ возможных комбинаций выбора предметов.

То есть более 536 миллионов. Похоже, такой перебор займёт некоторое время. Нельзя ли быстрее?

Стоит подумать о других вариантах. Что если начать с наиболее ценного предмета, затем следующего за ним по ценности, и так до тех пор, пока не заполнятся 20 квадратных метров? Такой алгоритм явно быстрее. Но даст ли он оптимальное решение? Есть сомнения. Как быстро решить задачу и найти лучшее решение?

Примечание: описанные выше случаи соответствуют полному перебору (метод «грубой силы», англ. brute force) и жадному (англ. greedy) алгоритму.

***

Динамическое программирование

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

К счастью, знакомый слышал об этом классе задач и подсказал вам более разумный способ справиться с проблемой. Он объяснил, что можно рекурсивно разделить проблему на более мелкие подзадачи. Сохраняя результаты в ячейках таблицы мемоизации и используя их на следующих итерациях, вы быстро найдёте оптимальное решение. Вы как бы обменяете программную память на время. То есть воспользуетесь методом динамического программирования.

Этапы решения задачи с помощью динамического программирования

  1. Создаём словарь со списком элементов и их параметрами (площадь, ценность).
  2. Создаём списки значений площади и ценности.
  3. Используем списки для построения таблиц мемоизации.
  4. Получаем элементы из последней строки таблицы. Последняя строка таблицы мемоизации содержит оптимальное решение. Возможно, существует несколько оптимальных решений. Например, когда есть два предмета с одинаковой площадью и стоимостью или ряд предметов имеют суммарные площадь и ценность, как у другого предмета.

Рассмотрим, как реализовать этот план на практике. Первый шаг мы предусмотрительно выполнили ранее, перейдём ко второму.

Создаём списки значений площади и ценности

Разделяем списки значений исходного словаря, например, так:

            def get_area_and_value(stuffdict):
    area = [stuffdict[item][0] for item in stuffdict]
    value = [stuffdict[item][1] for item in stuffdict]        
    return area, value
        

Используем списки для мемоизации

Пусть n – общее число предметов, A – их максимально допустимая суммарная площадь в новом жилище (2000 дм2). Составим таблицу из n + 1 строк и A + 1 столбцов. Строки пронумеруем индексом i, столбцы – индексом a (чтобы помнить что в столбцах площадь, area). То есть в качестве номеров столбцов мы рассматриваем дискретные значения площади, отличающиеся друг от друга на 1.

            def get_memtable(stuffdict, A=2000):
      area, value = get_area_and_value(stuffdict)
      n = len(value) # находим размеры таблицы
      
      # создаём таблицу из нулевых значений
      V = [[0 for a in range(A+1)] for i in range(n+1)]

      for i in range(n+1):
            for a in range(A+1):
                  # базовый случай
                  if i == 0 or a == 0:
                        V[i][a] = 0

                  # если площадь предмета меньше площади столбца,
                  # максимизируем значение суммарной ценности
                  elif area[i-1] <= a:
                        V[i][a] = max(value[i-1] + V[i-1][a-area[i-1]], V[i-1][a])

                  # если площадь предмета больше площади столбца,
                  # забираем значение ячейки из предыдущей строки
                  else:
                        V[i][a] = V[i-1][a]       
      return V, area, value
        

Вначале создаётся и заполняется таблица в виде вложенных списков. Нулевую строку и нулевой столбец заполняем нулями. Это базовый случай: когда площадь или количество элементов равны нулю, значение ячейки равно нулю. Далее таблица значений V будет заполняться строка за строкой слева направо и сверху вниз:


Если площадь текущего элемента меньше или равна площади (номеру столбца) текущей ячейки, вычисляем значение ячейки следуя правилу:

            V[i][a] = max(value[i-1] + V[i-1][a-area[i-1], V[i-1][a])
        

То есть выбираем максимальное из двух значений:

  1. Сумма ценности текущего предмета value[i-1] и величины элемента из предыдущей строки i-1 с площадью, меньшей на величину площади текущего предмета area[i-1]. Обратите внимание: нужно помнить, что элементы в таблице отличаются по нумерации на единицу из-за нулевой строки.
  2. Значение элемента предыдущей строки с той же площадью, то есть из того же столбца, что текущая ячейка. То же значение устанавливается в случае, если площадь текущей ячейки меньше, чем площадь текущего элемента (см. блок else)

За счёт такого подхода при одной и той же суммарной площади элементов происходит максимизация суммарной ценности.

Забираем нужные элементы из последней строки таблицы

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

            def get_selected_items_list(stuffdict, A=2000):
      V, area, value = get_memtable(stuffdict)
      n = len(value)
      res = V[n][A]      # начинаем с последнего элемента таблицы
      a = A              # начальная площадь - максимальная
      items_list = []    # список площадей и ценностей
    
      for i in range(n, 0, -1):  # идём в обратном порядке
            if res <= 0:  # условие прерывания - собрали "рюкзак" 
                  break
            if res == V[i-1][a]:  # ничего не делаем, двигаемся дальше
                  continue
            else:
                  # "забираем" предмет
                  items_list.append((area[i-1], value[i-1]))
                  res -= value[i-1]   # отнимаем значение ценности от общей
                  a -= area[i-1]  # отнимаем площадь от общей
            
      selected_stuff = []

      # находим ключи исходного словаря - названия предметов
      for search in items_list:
            for key, value in stuffdict.items():
                  if value == search:
                        selected_stuff.append(key)
            
      return selected_stuff
        

Итак, мы нашли список:

            >>> stuff = get_selected_items_list(stuffdict)
>>> print(stuff)
['bike_stand', 'garbage_can', 'standing_lamp', 'chest_of_drawers',
'plant_3', 'plant_2', 'diner_table_with_chairs', 'bookshelf',
'armchair', 'table', 'desk', 'bed', 'couch_s']
        

Проверим суммарные площадь и ценность собранных предметов:

            >>> totarea = sum([stuffdict[item][0] for item in stuff])
>>> totvalue = sum([stuffdict[item][1] for item in stuff])
>>> print(totarea)
2000
>>> print(totvalue)
715
        

Получилось! Собираем вещи и отправляемся в путь (звучит песня Mamas & Paps – San Francisco).

***

Бонус: Тепловая карта таблицы

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


Для построения использовалась библиотека matplotlib:

            def plot_memtable(V, stuffdict):
    plt.figure(figsize=(30,15))
    item_list = list(stuffdict.keys())
    item_list.insert(0, 'empty')
    sns.heatmap(V, yticklabels=item_list)
    plt.yticks(size=25)
    plt.xlabel('Area', size=25)
    plt.ylabel('Added item', size=25)
    plt.title('Value for Area with Set of Items', size=30)
    plt.show()
        

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

23
Янв
2020

Что нового в Pandas 1.0? 🐼

Pandas – популярная библиотека Python для работы с табличными данными, добавляющая к структуре массива NumPy именованные строки и столбцы, а также множество удобных методов. Pandas является одной из важных причин, почему Python стал доминирующим языком программирования в Data Science.

22
Янв
2020

21–22 февраля, Минск: конференция PyCon Belarus 2020

Ежегодная конференция для питонистов с обсуждением самых современных сфер применения языка и практикоориентированными воркшопами для спецов любого уровня.
— Читать дальше «Конференция PyCon Belarus 2020»

22
Янв
2020

8–9 февраля, Москва: хакатон Moscow Travel Hack

Хакатон, на котором от участников ждут решения, которые помогут создать новые проекты в области туризма и гостеприимства.
— Читать дальше «Хакатон Moscow Travel Hack»

22
Янв
2020

Обучение модели обнаружения объектов YOLO на пользовательском наборе данных

Рассматриваем подготовку собственного датасета и обучение YOLO на примере задачи распознавания шахматных фигур.

Нейросетевые модели обнаружения объектов делают много полезного. К…

17
Янв
2020

Наглядная шпаргалка по операциям с DataFrame в pandas для data wrangling и не только

Удобная и наглядная шпаргалка по основным операциям с DataFrame в pandas. Подходит для data wrangling и не только.
— Читать дальше «Наглядная шпаргалка по операциям с DataFrame в pandas для data wrangling и не только»

16
Янв
2020

Как повысить продуктивность при анализе данных? 25 неочевидных инструментов

Список бесплатных инструментов и библиотек для аналитиков данных. Заслуживающие внимания пакеты, программы и ресурсы, о которых не так часто упоминают, как о NumPy, Pandas или Jupyter.

Ниже представлен сжатый обзор 25 инструментов для самых разнообразных приложений науки о данных. Быстрый скрапинг веб-страниц и визуализация, анализ поведения клиентов и безопасное хранение ключей, работа в команде и развертывание моделей на облачных GPU.

В комментариях к публикации предлагаем поделиться своими любимыми библиотеками и инструментами.

Обзор DS инструментов:

  • Airtable: электронная таблица с мощью базы данных, альтернатива Google Sheets или Microsoft Excel. Отлично работает с Pandas, благодаря Python API. То что нужно для демонстрации результатов.
  • Orange: open source платформа, заточенная под машинное обучение и визуализацию данных, для которой не нужно уметь кодить. Качественная альтернатива Tableau или Power BI.
  • MarkDown: приложение для заметок на Node.js, полноценно работающее в офлайне с возможностью размещения на своём сервере.
  • Deepnote: приложение на базе Jupyter Notebook, созданное для совместной работы в реальном времени.

  • Dash by Plotly: JavaScript инструмент визуализации данных с открытым исходным кодом. Запустите готовую модель на Python или R, а Dash позаботится об остальном. Идеально подходит для создания мелких веб-приложений для показа клиенту.
  • KeeWeb: средство для безопасного хранения API-ключей и паролей.
  • MLxtend (сокр. от Machine Learning Extensions) – библиотека Python инструментов для повседневных задач обработки данных. Создатель – автор книги «Машинное обучение на Python» Себастьян Рашка.
            import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import itertools
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import EnsembleVoteClassifier
from mlxtend.data import iris_data
from mlxtend.plotting import plot_decision_regions

# Initializing Classifiers
clf1 = LogisticRegression(random_state=0)
clf2 = RandomForestClassifier(random_state=0)
clf3 = SVC(random_state=0, probability=True)
eclf = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3],
                              weights=[2, 1, 1], voting='soft')

# Loading some example data
X, y = iris_data()
X = X[:,[0, 2]]

# Plotting Decision Regions

gs = gridspec.GridSpec(2, 2)
fig = plt.figure(figsize=(10, 8))

labels = ['Logistic Regression', 'Random Forest', 
          'RBF kernel SVM', 'Ensemble']

for clf, lab, grd in zip([clf1, clf2, clf3, eclf],
                         labels,
                         itertools.product([0, 1],
                         repeat=2)):
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y,
                                clf=clf, legend=2)
    plt.title(lab)

plt.show() 
        

  • Lifetimes: библиотека для анализа поведения клиентов, прогнозирования прибыли и оттока
  • GitLab: альтернативное GitHub хранилище репозиториев с возможностью скрывать групповые репозитории. Удобно для закрытой командной работы и группового участия в ML-соревнованиях.
  • Draw.io: создания диаграмм для планирования проекта.
  • Spider: простой скраппер для веб-страниц в виде расширения Chrome. Можно скачивать страницы в CSV/JSON формате.
  • Simple Scraper: превратите любой сайт в API.
  • Airbnb Knowledge repo: ресурс для обмена знаниями между специалистами в области обработки данных и других технических профессий. Был создан для решения проблемы распространения знаний в рамках растущей команды.

  • Kyso: сервис помогает создать привлекательное и структурированное портфолио аналитика данных. Вы сможете просматривать чужие портфолио, увидите, как другие представляют себя и свои данные. Бесплатный период 14 дней.
  • LabelImg: графический инструмент для разметки объектов на картинках, добавление подписей и тегов изображений.

  • Reveal.js: фреймворк для создания HTML-презентаций. Многие аналитики используют его на своих выступлениях.
  • PythonAnywhere: простой способ развернуть онлайн лёгкий ML-проект на Python и сопутствующих библиотеках, если пока требуется лишь проверить гипотезу. В случае успеха легко перенести на AWS (руководство).
  • Sheety: превратите Google Sheet в API и моделируйте данные в реальном времени.
  • Jupyterthemes: устали от текущей темы Jupyter Notebook? Есть много других.
  • Light GBM: одна из популярных библиотек для односторонней выборки на основе градиента. В последние годы приобрела большую популярность, особенно на Kaggle.

  • Machine Learning A-Z: Practice Datasets and Codes: большое собрание данных и кода на Python и R, охватывающее популярные алгоритмы машинного обучения.
  • Gradient by Paperspace: запускайте блокноты Jupyter бесплатно на облачной машине, оснащённой графическими процессорами.
  • Glueviz: визуализируйте многомерные наборы данных. Бесплатный инструмент на основе Python (поставляется с Anaconda). Отлично подходит для поиска связей между наборами данных.

  • Hot dog or not hot dog?: мануал, не требующий знаний AI, машинного обучения и даже программирования. Руководство о том, как с IBM Watson написать программу для проверки, является ли объект хот-догом 🌭 или нет. Самый важный ресурс в подборке 😉
  • FloydHub Workspaces: облачная среда разработки для глубокого обучения. Можно запускать блокноты Jupyter, скрипты Python, использовать терминал и многое другое.

О чём-то не упомянули? Напишите, мы дополним статью вашими ссылками

15
Янв
2020

Опыт разработки: почему мы пишем инфраструктуру машинного обучения на Go, а не на Python

Разработчик Cortex Калеб Кайзер делится соображениями о преимуществах применения Go для инфраструктурных решений в ML-проектах и о том, как два языка могут дополнять друг друга.

Python – самый популярный яз…

12
Янв
2020

Иллюстрированное руководство по изменению формы массивов NumPy

Рассказываем, как перекраивать массивы NumPy в трех измерениях. Шпаргалка в конце руководства обобщает приемы работы с методами reshape, stack и ravel.

Трудность NumPy в том, что операции над многомерными массивами бывает сложно представить. Хаус Лин подготовил шпаргалки, которые сделают преобразование массивов нагляднее. Руководство подойдёт и для знакомства с NumPy.

1. Создаем массив NumPy

Аналог range для массивов. Чтобы создать простой массив, используем функцию np.arange(). Удобно взять небольшое составное число, например, 12.

            import numpy as np

a1 = np.arange(1, 13)  # числа от 1 до 12

print(a1.shape)
> (12,)

print(a1)
> [ 1  2  3  4  5  6  7  8  9 10 11 12] 
        
Создан одномерный массив из 12 чисел.

2. Изменяем форму с помощью метода reshape()

Оси и измерения. Чтобы изменить форму массива a1 , используем метод reshape(). Преобразуем одномерный массив из 12 чисел в двумерную таблицу размером 3×4. Первое число – количество строк, второе – столбцов. Строки соответствуют оси (англ. axis) 0, столбцы – оси 1. Ещё их называют измерениями (англ. dimensions).

            a1_2d = a1.reshape(3, 4)

print(a1_2d.shape)
> (3, 4)

print(a1_2d)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]] 
        

Автоматическое вычисление размерности. Если нужно, чтобы NumPy сам определил размер незаданного измерения, передайте на этой позиции значение -1:

            a1.reshape(3, 4)
a1.reshape(-1, 4)  # то же самое, что a1.reshape(3, 4)

a1.reshape(3, 4)
a1.reshape(3, -1)  # то же самое, что a1.reshape(3, 4)

a1.reshape(2, 6)
a1.reshape(2, -1)  # то же самое, что a1.reshape(2, 6) 
        

3. Изменяем форму по разным направлениям

Порядок переноса С. По умолчанию reshape() перестраивает исходный массив по оси 0. То есть в нашем примере отдельные числа из одномерного массива «переносятся» в двумерный построчно. Поведение можно изменить, передав значение параметру order. Дефолтный метод похож на то, как преобразование реализовано в C. Параметр order по умолчанию имеет значение 'C':

            a1.reshape(3, 4)
a1.reshape(3, 4, order='C') # даст идентичный результат
 
        

Порядок переноса Fortran. Если вы привыкли к тому, как преобразуются массивы в MATLAB, то это делается так же, как в Fortran. Поэтому используйте значение 'F':

            a1.reshape(3, 4, order='F')  # столбец за столбцом
> [[ 1  4  7 10]
   [ 2  5  8 11]
   [ 3  6  9 12]] 
        

Какую размерность имеет исходный массив a1? Может показаться, что массив a1 имеет размерность (1, 12). Но это одномерный массив с размерностью(12, ). Чтобы преобразовать одномерный массив к двумерному, используем метод reshape():

            print(a1)  # какая форма?
> [ 1  2  3  4  5  6  7  8  9 10 11 12]

print(a1.shape)
> (12,)

a1_1_by_12 = a1.reshape(1, -1)  # преобразуем к 1x12

print(a1_1_by_12)  # обратите внимание на двойные скобки
> [[ 1  2  3  4  5  6  7  8  9 10 11 12]]

print(a1_1_by_12.shape)  # двумерный массив
> (1, 12) 
        

4. Схлопываем массив до одномерного

Из 2D в 1D. Метод ravel() преобразует многомерные массивы в одномерные. Тот же параметр order определяет, «схлопнется» ли массив построчно или столбец за столбцом:

            print(a1_2d)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]

print(a1_2d.ravel())  # строка за строкой
> [ 1  2  3  4  5  6  7  8  9 10 11 12]

print(a1_2d.ravel(order='F'))  # столбец за столбцом
> [ 1  5  9  2  6 10  3  7 11  4  8 12] 
        

5. Повышаем размерность, сшивая массивы друг с другом


Создадим два массива:

            a1 = np.arange(1, 13)
print(a1)
> [ 1  2  3  4  5  6  7  8  9 10 11 12]

a2 = np.arange(13, 25)
print(a2)
> [13 14 15 16 17 18 19 20 21 22 23 24] 
        

Чтобы соединить два одномерных масива в двумерный, используем метод np.stack(). Параметр axis указывает индекс оси в результирующем массиве, по которой соединяются входные. По умолчанию axis = 0, и массивы стыкуются строка к строке:

            stack0 = np.stack((a1, a1, a2, a2))
print(stack0.shape)
> (4, 12)

print(stack0)
> [[ 1  2  3  4  5  6  7  8  9 10 11 12]
   [ 1  2  3  4  5  6  7  8  9 10 11 12]
   [13 14 15 16 17 18 19 20 21 22 23 24]
   [13 14 15 16 17 18 19 20 21 22 23 24]] 
        

Чтобы соединить массивы столбец к столбцу, явным образом передаем axis = 1:

            stack1 = np.stack((a1, a1, a2, a2), axis=1)
print(stack1.shape)
> (12, 4)
print(stack1)
> [[ 1  1 13 13]
   [ 2  2 14 14]
   [ 3  3 15 15]
   [ 4  4 16 16]
   [ 5  5 17 17]
   [ 6  6 18 18]
   [ 7  7 19 19]
   [ 8  8 20 20]
   [ 9  9 21 21]
   [10 10 22 22]
   [11 11 23 23]
   [12 12 24 24]] 
        

Как не повышать число измерений? Функция hstack() соединяет массивы горизонтально без изменения размерности. Если применить ее к одномерным массивам, получится длинный одномерный массив:

            stack_long = np.hstack((a1, a2))

print(stack_long.shape)
> (24,)

print(stack_long)
> [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24] 
        

6. Создаем трехмерный массив

Где применяются многомерные массивы? Массивы, живущие в трёх и более измерениях, активно используются в глубоком обучении. Например, для операций с изображениями. В работе с нейросетями преобразование многомерных массивов – обычное дело.

Для начала создадим два двумерных массива размером 3×4:

            a1 = np.arange(1, 13).reshape(3, -1)
a2 = np.arange(13, 25).reshape(3, -1)

print(a1)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]

print(a2)
> [[13 14 15 16]
   [17 18 19 20]
   [21 22 23 24]] 
        

Теперь соберём из них трёхмерный массив:

            a3_0 = np.stack((a1, a2))  # дефолтное axis=0, одна плоскость ложится на другую
a3_1 = np.stack((a1, a2), axis=1)
a3_2 = np.stack((a1, a2), axis=2)

print(a3_0.shape)
> (2, 3, 4)

print(a3_1.shape)
> (3, 2, 4)

print(a3_2.shape)
> (3, 4, 2) 
        

Как выглядят массивы:

            print(a3_0)
> [[[ 1  2  3  4]
    [ 5  6  7  8]
    [ 9 10 11 12]]

   [[13 14 15 16]
    [17 18 19 20]
    [21 22 23 24]]]

print(a3_1)
> [[[ 1  2  3  4]
    [13 14 15 16]]

   [[ 5  6  7  8]
    [17 18 19 20]]

   [[ 9 10 11 12]
    [21 22 23 24]]]

print(a3_2)
> [[[ 1 13]
    [ 2 14]
    [ 3 15]
    [ 4 16]]

   [[ 5 17]
    [ 6 18]
    [ 7 19]
    [ 8 20]]

   [[ 9 21]
    [10 22]
    [11 23]
    [12 24]]] 
        

Чтобы извлечь плоскость массива a1 из трехмерного, нужно передать 0 по соответствующему индексу оси:

            print(a1)
> [[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]

a3_0[0, :, :]
a3_1[:, 0, :]
a3_2[:, :, 0] 
        

Чтобы то же самое сделать для двумерного массива a2, на тех же позициях вместо 0 отправляем индекс 1. Символы двоеточия указывают, что нужно взять все элементы соответствующей оси.

7. Схлопываем многомерные массивы

Метод ravel() действует и для массивов с числом размерностей больше 2:


            print(a3_0)
> [[[ 1  2  3  4]
    [ 5  6  7  8]
    [ 9 10 11 12]]

   [[13 14 15 16]
    [17 18 19 20]
    [21 22 23 24]]]

print(a3_0.ravel())
> [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]

print(a3_0.ravel(order='F'))
> [ 1 13  5 17  9 21  2 14  6 18 10 22  3 15  7 19 11 23  4 16  8 20 12 24] 
        

8. Изменяем форму многомерных массивов

Метод reshape() также работает с массивами любой размерности. Главное условие, которое нужно соблюдать – количество элементов в массиве не должно меняться:

            print(a3_0)  # исходный размер 2x3x4
> [[[ 1  2  3  4]
    [ 5  6  7  8]
    [ 9 10 11 12]]

   [[13 14 15 16]
    [17 18 19 20]
    [21 22 23 24]]]

print(a3_0.reshape(4, -1))  # преобразуем к 4x6
> [[ 1  2  3  4  5  6]
   [ 7  8  9 10 11 12]
   [13 14 15 16 17 18]
   [19 20 21 22 23 24]]

print(a3_0.reshape(4, -1, order='F'))  # делаем то же самое, но в F-стиле
> [[ 1  9  6  3 11  8]
   [13 21 18 15 23 20]
   [ 5  2 10  7  4 12]
   [17 14 22 19 16 24]]

print(a3_0.reshape(4, 2, 3))  # преобразуем к трехмерному массиву другой формы
> [[[ 1  2  3]
    [ 4  5  6]]
   [[ 7  8  9]
    [10 11 12]]
   [[13 14 15]
    [16 17 18]]
   [[19 20 21]
    [22 23 24]]] 
        

Заключение

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


11
Дек
2019

Голосовой DeepFake, или Как работает технология клонирования голоса

Как научить искусственный интеллект читать текст любым голосом? Рассказываем, что известно о технологии клонирования голоса, на примере открытого репозитория Real-Time Voice Cloning.

Проблема синтеза речи и…

25
Ноя
2019

29 ноября – 1 декабря, Новосибирск: конференция DevFest

Ежегодное мероприятие, которое проводит сообщество GDG. За три дня можно послушать доклады про мобильную и веб-разработку, машинное обучение и безопасность.
— Читать дальше «Конференция DevFest Siberia 2019»

23
Сен
2019

19–20 октября, Екатеринбург: HACKATHON BEST URFU 2019

Хакатон для студентов технических специальностей вузов Екатеринбурга. Задачи в сферах Data Science и веб-разработки разработали в телеком-компании «МОТИВ».
— Читать дальше «HACKATHON BEST URFU 2019»