Игра в Бога с данными

5 проблем с синтетическими данными и код для оценки новых подходов к машинному обучению

Итак, у вас есть подход к машинному обучению, который вы хотите опробовать. Отлично, но как вы докажете его ценность? Ответ: синтетические данные.

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

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

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

Давайте начнем!

Проблема кольца

Эта проблема

В задаче 2D-классификации кольцевого пространства есть две окружности с центрами (0,5, 0,5). Кольцо определяется двумя окружностями - внешней с радиусом 0,5 и внутренней с радиусом 0,3.

Все точки данных, попадающие в область перекрытия красной и синей областей, помечены как 1; в противном случае они помечаются как 0.

Задача с кольцевым пространством, записанная как функция, выглядит так:

На диаграмме ниже красная точка представляет 1, а синяя точка - 0.

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

Расширения

  • Добавление шума. Шумная версия этой задачи классификации может быть построена с гауссовым шумом вдоль границы решения. В приведенном ниже уравнении z - это вектор случайных чисел, взятый из положительной стороны распределения Гаусса со стандартным отклонением s.

  • Задача о кольцевом пространстве для размеров 3+. Другой вариант проблемы с кольцевым пространством можно адаптировать для трех или более измерений, просто добавив еще одно измерение в уравнение.

Код

Предоставляются четыре параметра:

  • n, количество точек данных
  • innerRadius, радиус внутреннего круга
  • outerRadius, радиус внешнего круга
  • z, шкала нормального распределения, к которому добавляется случайность

… Которые можно настроить, чтобы настроить свойства данных.

import pandas as pd
import numpy as np
import math as m
import random as r
n = 800 #number of data points
innerRadius = 0.3 #radius of inner circle
outerRadius = 0.5 #radius of outer circle
z = 0 #gaussian multiplier
data = {'x1':[],'x2':[],'label':[]}
for i in range(n):
	x1 = r.randint(1,100_000)/100_000
	x2 = r.randint(1,100_000)/100_000
	coef = abs(np.random.normal(scale=z))
	if (x1-0.5)**2 + (x2-0.5)**2 > (innerRadius-coef)**2:
		if (x1-0.5)**2 + (x2-0.5)**2 < (outerRadius-coef)**2:
			label = 1
		else:
			label = 0
	else:
		label = 0
	data['x1'].append(x1)
	data['x2'].append(x2)
	data['label'].append(label)
data = pd.DataFrame(data

Первые 10 строк вывода данных:

Чтобы построить кольцевое пространство:

import seaborn as sns
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5,5))
sns.scatterplot(data['x1'],data['x2'],data['label'])

400 точек данных без шума:

400 точек данных с z = 0,1:

400 точек данных с z = 0,25:

Приложение данных

Во многих реальных наборах данных, таких как медицинские диагнозы, есть пространства признаков, в которых метки разделены более четко. Модель, которая успешно справляется с проблемой кольцевого пространства с разумным количеством шума (z = 0,1–0,2), может распознавать геометрически очевидные и нелинейные закономерности в реальных данных и имеет разумную устойчивость к шуму. Увеличивая или уменьшая площадь кольцевого пространства, модель может быть адаптирована для решения сбалансированных или несбалансированных задач. При уменьшении площади фиброзного кольца проблема становится несбалансированной и напоминает медицинские проблемы, такие как диагностика рака, когда количество положительных диагнозов намного меньше, чем количество отрицательных диагнозов. Увеличивая площадь кольцевого пространства до половины площади сетки, проблема становится более сбалансированной, что может быть полезно при идентификации мужчин и женщин, моложе 18 или старше 18 лет и т. Д. Сравните геометрически очевидные проблемы с задачей шахматной доски.

Задача двоичной классификации шахматной доски

Эта проблема

Как и на шахматной доске, чередующиеся двумерные пробелы помечены как 0 и 1. Все значения 1 (красный) имеют значения x1 и x2 одинаковой четности (либо оба четных или оба нечетные), в то время как все значения 0 (синий) имеют значения x1 и x2 противоположной четности.

Наглядное изображение представлено ниже:

Математически это можно представить как

Одно из решений проблемы с шахматной доской выглядит следующим образом:

Каждая диагональная линия разделяет точки на соответствующие цвета.

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

Расширения

  • Задачу шахматной доски можно расширить, добавив n цветов.
  • Задачу также можно преобразовать в трехмерную или m- D-шахматную задачу.

Код

В задаче шахматной доски настраиваемые параметры:

  • dim1, первое измерение двумерного пространства
  • dim2, второе измерение двумерного пространства
import pandas as pd
dim1 = 20 #x-dimension
dim2 = 20 #y-dimension
data = {'x1':[],'x2':[],'label':[]}
for xcoor in range(dim1):
    for ycoor in range(dim2):
        if xcoor % 2 == 0 and ycoor % 2 == 0:
            label = 1
        elif xcoor % 2 == 1 and ycoor % 2 == 1:
            label = 1
        else:
            label = 0
        data['x1'].append(xcoor)
        data['x2'].append(ycoor)
        data['label'].append(label)
data = pd.DataFrame(data)

Фрейм данных выглядит так:

… Который можно представить как

import seaborn as sns
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5,5))
sns.scatterplot(data['x1'],data['x2'],data['label'])

Приложение данных

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

X-мерная задача двоичной классификации четности

Эта проблема

В проблеме четности X-Dimensional (по умолчанию X = 10) битовая строка X классифицируется как 1, если она имеет нечетное число единиц (следовательно, нечетное число нулей) и категоризируется как 0, если он имеет четное количество единиц (следовательно, четное количество нулей). Эта проблема четности нелинейна.

Ценность проблемы X-Dimensional Parity заключается в том, что между всеми столбцами существует более глубокая математическая взаимосвязь, а не один столбец, который является наиболее важным. Это могла быть проблема шахматной доски без геометрического аспекта; проблема четности не может быть проанализирована геометрически.

Расширения

  • Дополнительные столбцы шума, которые действуют как шум.
  • Увеличьте диапазон значений (вместо только 0 и 1, возможно, 0, 1, 2 и 3) - последняя метка будет 1, например, если количество 3 нечетное.

Код

import pandas as pd
import numpy as np
import random as r
dimensions = 10 #bitstring dimensions
data_points = 500 #number of data points
data = {'label':[]}
for dimension in range(dimensions):
    data['d'+str(dimension+1)] = []
    
for i in range(data_points):
    bitstring = [r.randint(0,1) for i in range(dimensions)]
    count0 = 0
    for i in range(len(bitstring)):
        if bitstring[i] == 0:
            count0 += 1
        data['d'+str(i+1)].append(bitstring[i])
    if count0 % 2 == 0:
        data['label'].append(0)
    else:
        data['label'].append(1)
data = pd.DataFrame(data)

Это выводит DataFrame:

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

from sklearn import decomposition
pca = decomposition.PCA(n_components=2)
pca.fit(data.drop('label',axis=1))
X = pca.transform(data.drop('label',axis=1))
pca.explained_variance_.sum()

Это выводит:

0.5922694981939761

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

Построение данных:

import seaborn as sns
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5,5))
sns.scatterplot(X[:,0],X[:,1],data['label'])

Понятно, что нет четкого геометрического узора, четко определяющего этикетку.

Приложение для передачи данных

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

Проблема двоичной классификации XOR

Проблема

Есть две функции, значения XOR которых создают конечную цель, и дополнительные случайные функции x в виде шума. По умолчанию x равно 97 (всего 100 столбцов, включая столбец метки).

Функция XOR действует как таковая:

  • 0, 0 : 0
  • 1, 1 : 0
  • 0, 1: 1
  • 1, 0: 1

Если оба входа одинаковы, на выходе будет 0; в противном случае на выходе будет 1.

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

Код

Параметры, которые можно настроить:

  • noise_features, количество случайных шумовых характеристик в данных.
  • data_points, количество точек данных
import pandas as pd
import random
noise_features = 97
data_points = 500
def XOR(bit1,bit2):
    if bit1 and bit2:
        return 0
    elif not bit1 and not bit2:
        return 0
    else:
        return 1
data = {'label':[],'bit1':[],'bit2':[]}
for index in range(noise_features):
    data['nf'+str(index)] = []
for i in range(data_points):
    bit1 = random.randint(0,1)
    bit2 = random.randint(0,1)
    label = XOR(bit1,bit2)
    data['label'].append(label)
    data['bit1'].append(bit1)
    data['bit2'].append(bit2)
    for noise_index in range(noise_features):
        data['nf'+str(noise_index)].append(random.randint(0,1))
data = pd.DataFrame(data)

Выходной DataFrame («nf» означает «шумовая характеристика»):

Приложение данных

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

Проблема корреляции

Проблема

Набор данных Corral имеет 6 двоичных функций, а метка определяется (f 1 И f 2) ИЛИ (f 3 И f 4), где fn обозначает вход nt h. Любое дополнительное количество функций n (по умолчанию 1) имеет корреляцию m% (по умолчанию 75%) с меткой класса и любое число p (по умолчанию 5) могут быть добавлены дополнительные случайные функции.

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

Код

Параметры, которые можно настроить:

  • data_points, количество точек данных
  • random_features, количество случайных функций
  • corr_features, количество функций, связанных с целью
  • корреляция, процент корреляции коррелированных функций с целью.
import pandas as pd
import random
data_points = 500 #number of data points
random_features = 5 #number of random features
corr_features = 1 #number of correlated features
correlation = 75 #% correlation with target
def logic_oracle(f1,f2,f3,f4):
    if f1 and f2:
        return 1
    elif f3 and f4:
        return 1
    else:
        return 0
data = {'label':[],'f1':[],'f2':[],'f3':[],'f4':[]}
for corr_feature in range(corr_features):
    data['corr'+str(corr_feature+1)] = []
for rand_feature in range(random_features):
    data['rand'+str(rand_feature+1)] = []
for i in range(data_points):
    f1 = random.randint(0,1)
    f2 = random.randint(0,1)
    f3 = random.randint(0,1)
    f4 = random.randint(0,1)
    label = logic_oracle(f1,f2,f3,f4)
    data['f1'].append(f1)
    data['f2'].append(f2)
    data['f3'].append(f3)
    data['f4'].append(f4)
    data['label'].append(label)
    for index in range(random_features):
        data['rand'+str(index+1)].append(random.randint(0,1))
for corr_feature in range(corr_features):
    for label in data['label']:
        if random.randint(1,100) < correlation:
            data['corr'+str(corr_feature+1)].append(int(label))
        else:
            data['corr'+str(corr_feature+1)].append(int(not label))
data = pd.DataFrame(data)

Выходной DataFrame:

Приложение данных

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

Спасибо за прочтение!