Создать больший синтетический набор данных на основе меньшего набора данных в Python - PullRequest
2 голосов
/ 06 марта 2019

У меня есть набор данных с 21000 строками (выборками данных) и 102 столбцами (функциями).Я хотел бы иметь больший синтетический набор данных, сгенерированный на основе текущего набора данных, скажем, с 100000 строк, чтобы я мог таким образом использовать его для целей машинного обучения.

Я имел в виду ответ @Prashant наэтот пост https://stats.stackexchange.com/questions/215938/generate-synthetic-data-to-match-sample-data,, но я не могу заставить его работать над созданием большего синтетического набора данных для моих данных.

import numpy as np
from random import randrange, choice
from sklearn.neighbors import NearestNeighbors
import pandas as pd
#referring to https://stats.stackexchange.com/questions/215938/generate-synthetic-data-to-match-sample-data


df = pd.read_pickle('df_saved.pkl')
df = df.iloc[:,:-1] # this gives me df, the final Dataframe which I would like to generate a larger dataset based on. This is the smaller Dataframe with 21000x102 dimensions.


def SMOTE(T, N, k):
# """
# Returns (N/100) * n_minority_samples synthetic minority samples.
#
# Parameters
# ----------
# T : array-like, shape = [n_minority_samples, n_features]
#     Holds the minority samples
# N : percetange of new synthetic samples:
#     n_synthetic_samples = N/100 * n_minority_samples. Can be < 100.
# k : int. Number of nearest neighbours.
#
# Returns
# -------
# S : array, shape = [(N/100) * n_minority_samples, n_features]
# """
    n_minority_samples, n_features = T.shape

    if N < 100:
       #create synthetic samples only for a subset of T.
       #TODO: select random minortiy samples
       N = 100
       pass

    if (N % 100) != 0:
       raise ValueError("N must be < 100 or multiple of 100")

    N = N/100
    n_synthetic_samples = N * n_minority_samples
    n_synthetic_samples = int(n_synthetic_samples)
    n_features = int(n_features)
    S = np.zeros(shape=(n_synthetic_samples, n_features))

    #Learn nearest neighbours
    neigh = NearestNeighbors(n_neighbors = k)
    neigh.fit(T)

    #Calculate synthetic samples
    for i in range(n_minority_samples):
       nn = neigh.kneighbors(T[i], return_distance=False)
       for n in range(N):
          nn_index = choice(nn[0])
          #NOTE: nn includes T[i], we don't want to select it
          while nn_index == i:
             nn_index = choice(nn[0])

          dif = T[nn_index] - T[i]
          gap = np.random.random()
          S[n + i * N, :] = T[i,:] + gap * dif[:]

    return S

df = df.to_numpy()
new_data = SMOTE(df,50,10) # this is where I call the function and expect new_data to be generated with larger number of samples than original df.

Отслеживание полученной мной ошибки упоминается ниже: -

Traceback (most recent call last):
  File "MyScript.py", line 66, in <module>
    new_data = SMOTE(df,50,10)
  File "MyScript.py", line 52, in SMOTE
    nn = neigh.kneighbors(T[i], return_distance=False)
  File "/trinity/clustervision/CentOS/7/apps/anaconda/4.3.31/3.6-VE/lib/python3.5/site-packages/sklearn/neighbors/base.py", line 393, in kneighbors
    X = check_array(X, accept_sparse='csr')
  File "/trinity/clustervision/CentOS/7/apps/anaconda/4.3.31/3.6-VE/lib/python3.5/site-packages/sklearn/utils/validation.py", line 547, in check_array
    "if it contains a single sample.".format(array))
ValueError: Expected 2D array, got 1D array instead:

Я знаю, что эта ошибка (ожидаемый двумерный массив, полученный одномерный массив) возникает в строке nn = neigh.kneighbors(T[i], return_distance=False).Точно, когда я вызываю функцию, T является массивом numpy формы (21000x102), мои данные, которые я преобразую из Pandas Dataframe в массив numpy.Я знаю, что в этом вопросе могут быть похожие дубликаты, но ни один из них не отвечает на мой вопрос.Любая помощь в этом отношении будет высоко оценена.

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

Так что T [i] дает ему массив с формой (102,).

Функция ожидает массив с формой (1, 102).

Вы можете получить это, позвонив в форму reshape:

nn = neigh.kneighbors(T[i].reshape(1, -1), return_distance=False)

В случае, если вы не знакомы с np.reshape, в 1 указывается, что первое измерение должно быть размером 1, а в -1 указывается, что второе измерение должно быть тем, на которое когда-либо передавал его размер numpy; в этом случае оригинал 102.

1 голос
/ 09 марта 2019

Может быть полезно для вас

SMOTE и другие передовые методы сверхсэмплинга

Этот пакет imblearn имеет API-интерфейс sklearn и множество методов передискретизации.

...