Генерация синтетических данных с помощью Numpy и Scikit-Learn

Введение В этом руководстве мы обсудим детали создания различных синтетических наборов данных с использованием библиотек Numpy и Scikit-learn. Мы увидим, как можно сгенерировать разные образцы из разных распределений с известными параметрами. Мы также обсудим создание наборов данных для различных целей, таких как регрессия, классификация и кластеризация. В конце мы увидим, как мы можем создать набор данных, который имитирует распределение существующего набора данных. Потребность в синтетических данных в данных sc

Вступление

В этом руководстве мы обсудим детали создания различных синтетических наборов данных с использованием библиотек Numpy и Scikit-learn . Мы увидим, как можно сгенерировать разные образцы из разных распределений с известными параметрами.

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

Потребность в синтетических данных

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

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

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

Настройка

Прежде чем писать код для генерации синтетических данных, давайте импортируем необходимые библиотеки:

 import numpy as np 
 
 # Needed for plotting 
 import matplotlib.colors 
 import matplotlib.pyplot as plt 
 from mpl_toolkits.mplot3d import Axes3D 
 
 # Needed for generating classification, regression and clustering datasets 
 import sklearn.datasets as dt 
 
 # Needed for generating data from an existing dataset 
 from sklearn.neighbors import KernelDensity 
 from sklearn.model_selection import GridSearchCV 

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

 # Define the seed so that results can be reproduced 
 seed = 11 
 rand_state = 11 
 
 # Define the color maps for plots 
 color_map = plt.cm.get_cmap('RdYlBu') 
 color_map_discrete = matplotlib.colors.LinearSegmentedColormap.from_list("", ["red","cyan","magenta","blue"]) 

Создание одномерных выборок из известных распределений

Теперь мы поговорим о создании точек выборки из известных распределений в 1D.

Модуль random от numpy предлагает широкий спектр способов генерации случайных чисел, выбранных из известного распределения с фиксированным набором параметров. В целях воспроизведения мы передадим seed RandomState и пока мы будем использовать то же начальное значение, мы получим те же числа.

Давайте определим список распределения, такой как uniform , normal , exponential и т. Д., Список параметров и список цветов, чтобы мы могли визуально различать их:

 rand = np.random.RandomState(seed) 
 
 dist_list = ['uniform','normal','exponential','lognormal','chisquare','beta'] 
 param_list = ['-1,1','0,1','1','0,1','2','0.5,0.9'] 
 colors_list = ['green','blue','yellow','cyan','magenta','pink'] 

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

Это делается с помощью функции eval() , которую мы используем для генерации выражения Python. Например, мы можем использовать rand.exponential(1, 5000) для генерации выборок из экспоненциального распределения масштаба 1 и размера 5000 .

Здесь мы будем использовать наши dist_list , param_list и color_list для генерации этих вызовов:

 fig,ax = plt.subplots(nrows=2, ncols=3,figsize=(12,7)) 
 plt_ind_list = np.arange(6)+231 
 
 for dist, plt_ind, param, colors in zip(dist_list, plt_ind_list, param_list, colors_list): 
 x = eval('rand.'+dist+'('+param+',5000)') 
 
 plt.subplot(plt_ind) 
 plt.hist(x,bins=50,color=colors) 
 plt.title(dist) 
 
 fig.subplots_adjust(hspace=0.4,wspace=.3) 
 plt.suptitle('Sampling from Various Distributions',fontsize=20) 
 plt.show() 

Это приводит к:

создание 1d образцов с помощьюnumpy{.ezlazyload}

Синтетические данные для регрессии

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

Функция make_regression() возвращает набор точек входных данных (регрессоров) вместе с их выходными данными (целью). Эту функцию можно настроить с помощью следующих параметров:

  1. n_features - количество измерений / характеристик сгенерированных данных
  2. noise - стандартное отклонение гауссовского шума
  3. n_samples - количество образцов

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

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

В приведенном ниже коде синтетические данные были сгенерированы для разных уровней шума и состоят из двух входных функций и одной целевой переменной. Изменяющийся цвет точек ввода показывает изменение целевого значения, соответствующего точке данных. Данные генерируются в 2D для лучшей визуализации, но многомерные данные могут быть созданы с n_features параметра n_features:

 map_colors = plt.cm.get_cmap('RdYlBu') 
 fig,ax = plt.subplots(nrows=2, ncols=3,figsize=(16,7)) 
 plt_ind_list = np.arange(6)+231 
 
 for noise,plt_ind in zip([0,0.1,1,10,100,1000],plt_ind_list): 
 x,y = dt.make_regression(n_samples=1000, 
 n_features=2, 
 noise=noise, 
 random_state=rand_state) 
 
 plt.subplot(plt_ind) 
 my_scatter_plot = plt.scatter(x[:,0], 
 x[:,1], 
 c=y, 
 vmin=min(y), 
 vmax=max(y), 
 s=35, 
 cmap=color_map) 
 
 plt.title('noise: '+str(noise)) 
 plt.colorbar(my_scatter_plot) 
 
 fig.subplots_adjust(hspace=0.3,wspace=.3) 
 plt.suptitle('make_regression() With Different Noise Levels',fontsize=20) 
 plt.show() 

Здесь мы создали пул из 1000 выборок с двумя входными переменными (функциями). В зависимости от уровня шума ( 0..1000 ) мы можем увидеть, как сгенерированные данные существенно различаются на диаграмме рассеяния:

создание синтетических данных длярегрессии{.ezlazyload}

Семейство функций make_friedman

Существует три версии функции make_friedman?() (Замените ? значение из {1,2,3} ).

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

  • make_friedman1() : n_features этой функции должен быть не менее 5, следовательно, минимальное количество входных измерений 5. Здесь цель задается:
    $
    y (x) = 10 * \ sin (\ pi x_0 x_1) + 20 (x_2 - 0,5) ^ 2 + 10x_3 + 5x_4 + \ text {noise}
    $

  • make_friedman2() : сгенерированные данные имеют 4 входных измерения. Переменная ответа задается следующим образом:

$$
y (x) = \ sqrt {(x_0 ^ 2 + x_1 x_2 - \ frac {1} {(x_1 x_3) ^ 2})} + \ text {noise}
$

  • make_friedman3() : сгенерированные данные в этом случае также имеют 4 измерения. Выходная переменная задается следующим образом:

$$
y (x) = \ arctan (\ frac {x_1 x_2 - \ frac {1} {(x_1 x_3)}} {x_0}) + \ text {noise}
$

Приведенный ниже код генерирует наборы данных с использованием этих функций и отображает первые три функции в 3D, причем цвета меняются в зависимости от целевой переменной:

 fig = plt.figure(figsize=(18,5)) 
 
 x,y = dt.make_friedman1(n_samples=1000,n_features=5,random_state=rand_state) 
 ax = fig.add_subplot(131, projection='3d') 
 my_scatter_plot = ax.scatter(x[:,0], x[:,1],x[:,2], c=y, cmap=color_map) 
 fig.colorbar(my_scatter_plot) 
 plt.title('make_friedman1') 
 
 x,y = dt.make_friedman2(n_samples=1000,random_state=rand_state) 
 ax = fig.add_subplot(132, projection='3d') 
 my_scatter_plot = ax.scatter(x[:,0], x[:,1],x[:,2], c=y, cmap=color_map) 
 fig.colorbar(my_scatter_plot) 
 plt.title('make_friedman2') 
 
 x,y = dt.make_friedman3(n_samples=1000,random_state=rand_state) 
 ax = fig.add_subplot(133, projection='3d') 
 my_scatter_plot = ax.scatter(x[:,0], x[:,1],x[:,2], c=y, cmap=color_map) 
 fig.colorbar(my_scatter_plot) 
 plt.suptitle('make_friedman?() for Non-Linear Data',fontsize=20) 
 plt.title('make_friedman3') 
 
 plt.show() 

сделать семейство функцийФридмана{.ezlazyload}

Синтетические данные для классификации

Scikit-learn имеет простые и удобные функции для создания наборов данных для классификации в модуле sklearn.dataset Давайте рассмотрим пару примеров.

make_classification() для задач классификации n-классов

Для задач классификации n-классов make_classification() имеет несколько вариантов:

  1. class_sep : указывает, должны ли различные классы быть более распределенными и легче различать
  2. n_features : Количество функций
  3. n_redundant : количество избыточных функций
  4. n_repeated : количество повторяющихся функций
  5. n_classes : Общее количество классов

Создадим набор классификационных данных для двумерных входных данных. У нас будут разные значения class_sep для задачи двоичной классификации. Точки одного цвета относятся к одному классу. Стоит отметить, что эта функция также может генерировать несбалансированные классы:

 fig,ax = plt.subplots(nrows=1, ncols=3,figsize=(16,5)) 
 plt_ind_list = np.arange(3)+131 
 
 for class_sep,plt_ind in zip([0.1,1,10],plt_ind_list): 
 x,y = dt.make_classification(n_samples=1000, 
 n_features=2, 
 n_repeated=0, 
 class_sep=class_sep, 
 n_redundant=0, 
 random_state=rand_state) 
 
 plt.subplot(plt_ind) 
 my_scatter_plot = plt.scatter(x[:,0], 
 x[:,1], 
 c=y, 
 vmin=min(y), 
 vmax=max(y), 
 s=35, 
 cmap=color_map_discrete) 
 plt.title('class_sep: '+str(class_sep)) 
 
 fig.subplots_adjust(hspace=0.3,wspace=.3) 
 plt.suptitle('make_classification() With Different class_sep Values',fontsize=20) 
 plt.show() 

сделать классификацию поn-классам{.ezlazyload}

make_multilabel_classification() для задач классификации с несколькими метками

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

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

 fig,ax = plt.subplots(nrows=1, ncols=3,figsize=(16,5)) 
 plt_ind_list = np.arange(3)+131 
 
 for label,plt_ind in zip([2,3,4],plt_ind_list): 
 x,y = dt.make_multilabel_classification(n_samples=1000, 
 n_features=2, 
 n_labels=label, 
 n_classes=4, 
 random_state=rand_state) 
 target = np.sum(y*[8,4,2,1],axis=1) 
 
 plt.subplot(plt_ind) 
 my_scatter_plot = plt.scatter(x[:,0], 
 x[:,1], 
 c=target, 
 vmin=min(target), 
 vmax=max(target), 
 cmap=color_map) 
 plt.title('n_labels: '+str(label)) 
 
 fig.subplots_adjust(hspace=0.3,wspace=.3) 
 plt.suptitle('make_multilabel_classification() With Different n_labels Values',fontsize=20) 
 plt.show() 

многозначнаяклассификация{.ezlazyload}

Синтетические данные для кластеризации

Для кластеризации sklearn.datasets предоставляет несколько вариантов. Здесь мы рассмотрим функции make_blobs() и make_circles() .

make_blobs()

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

Здесь мы проиллюстрируем эту функцию в 2D и покажем, как точки данных меняются с разными значениями параметра cluster_std

 fig,ax = plt.subplots(nrows=1, ncols=3,figsize=(16,5)) 
 plt_ind_list = np.arange(3)+131 
 
 for std,plt_ind in zip([0.5,1,10],plt_ind_list): 
 x, label = dt.make_blobs(n_features=2, 
 centers=4, 
 cluster_std=std, 
 random_state=rand_state) 
 
 plt.subplot(plt_ind) 
 my_scatter_plot = plt.scatter(x[:,0], 
 x[:,1], 
 c=label, 
 vmin=min(label), 
 vmax=max(label), 
 cmap=color_map_discrete) 
 plt.title('cluster_std: '+str(std)) 
 
 fig.subplots_adjust(hspace=0.3,wspace=.3) 
 plt.suptitle('make_blobs() With Different cluster_std Values',fontsize=20) 
 plt.show() 

синтетические данные длякластеризации{.ezlazyload}

make_circles()

Функция make_circles() генерирует две концентрические окружности с одним и тем же центром, расположенные одна внутри другой.

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

 fig,ax = plt.subplots(nrows=1, ncols=3,figsize=(16,5)) 
 plt_ind_list = np.arange(3)+131 
 
 for noise,plt_ind in zip([0,0.1,1],plt_ind_list): 
 x, label = dt.make_circles(noise=noise,random_state=rand_state) 
 
 plt.subplot(plt_ind) 
 my_scatter_plot = plt.scatter(x[:,0], 
 x[:,1], 
 c=label, 
 vmin=min(label), 
 vmax=max(label), 
 cmap=color_map_discrete) 
 plt.title('noise: '+str(noise)) 
 
 fig.subplots_adjust(hspace=0.3,wspace=.3) 
 plt.suptitle('make_circles() With Different Noise Levels',fontsize=20) 
 plt.show() 

создать круги синтетическихданных{.ezlazyload}

Генерация выборок, полученных из входного набора данных

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

Чтобы визуализировать только что сгенерированные образцы, давайте посмотрим на набор данных лиц Olivetti, который можно получить с помощью sklearn.datasets.fetch_olivetti_faces() . Набор данных содержит 10 разных изображений лиц 40 разных людей.

Вот что мы будем делать:

  1. Получить данные о лицах
  2. Сгенерируйте модель плотности ядра из данных
  3. Используйте плотность ядра для генерации новых выборок данных
  4. Покажите оригинальные и синтетические лица.
1
<!-- -->
 # Fetch the dataset and store in X 
 faces = dt.fetch_olivetti_faces() 
 X= faces.data 
 
 # Fit a kernel density model using GridSearchCV to determine the best parameter for bandwidth 
 bandwidth_params = {'bandwidth': np.arange(0.01,1,0.05)} 
 grid_search = GridSearchCV(KernelDensity(), bandwidth_params) 
 grid_search.fit(X) 
 kde = grid_search.best_estimator_ 
 
 # Generate/sample 8 new faces from this dataset 
 new_faces = kde.sample(8, random_state=rand_state) 
 
 # Show a sample of 8 original face images and 8 generated faces derived from the faces dataset 
 fig,ax = plt.subplots(nrows=2, ncols=8,figsize=(18,6),subplot_kw=dict(xticks=[], yticks=[])) 
 for i in np.arange(8): 
 ax[0,i].imshow(X[10*i,:].reshape(64,64),cmap=plt.cm.gray) 
 ax[1,i].imshow(new_faces[i,:].reshape(64,64),cmap=plt.cm.gray) 
 ax[0,3].set_title('Original Data',fontsize=20) 
 ax[1,3].set_title('Synthetic Data',fontsize=20) 
 fig.subplots_adjust(wspace=.1) 
 plt.show() 

создание синтетических данных на основеввода{.ezlazyload}

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

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

Выводы

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

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

comments powered by Disqus