6
votes

Générez un ensemble de données synthétiques plus grand basé sur un ensemble de données plus petit en Python

J'ai un ensemble de données avec 21000 lignes (échantillons de données) et 102 colonnes (entités). J'aimerais avoir un plus grand ensemble de données synthétiques généré sur la base de l'ensemble de données actuel, disons avec 100000 lignes, afin que je puisse l'utiliser à des fins d'apprentissage automatique.

J'ai fait référence à la réponse de @Prashant sur ce post https://stats.stackexchange.com/questions/215938/generate-synthetic -data-to-match-sample-data , mais je ne parviens pas à le faire fonctionner pour générer un plus grand ensemble de données synthétiques pour mes données.

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:

Le traçage de l'erreur que j'obtiens est mentionnée ci-dessous: -

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.

Je sais que cette erreur (tableau 2D attendu, tableau 1D) se produit sur la ligne nn = hennir. genoux voisins (T [i], return_distance = False) . Précisément, lorsque j'appelle la fonction, T est le tableau numpy de forme (21000x102), mes données que je convertis d'un Pandas Dataframe en un tableau numpy . Je sais que cette question peut avoir des doublons similaires, mais aucun d'entre eux ne répond à ma question. Toute aide à cet égard serait très appréciée.


0 commentaires

3 Réponses :


2
votes

Donc ce que T [i] lui donne est un tableau avec forme (102,).

Ce que la fonction attend est un tableau avec forme (1, 102).

Vous pouvez obtenir ceci en appelant reshape dessus:

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

Au cas où vous ne seriez pas familier avec np.reshape, le 1 indique que la première dimension doit être de taille 1, et le -1 dit que la deuxième dimension devrait être la taille que numpy peut diffuser; dans ce cas, l'original 102.


0 commentaires

1
votes

Peut vous être utile

SMOTE et autres techniques avancées de sur-échantillonnage

Ce package imblearn a sklearn comme API et beaucoup de suréchantillonnage techniques.


0 commentaires

0
votes

J'ai eu le même problème. J'ai fait des recherches pendant un moment, mais je n'ai pas pu trouver de solution appropriée, puis j'ai essayé d'appliquer ma propre solution à ce problème. Cela m'a aidé et j'espère que cela fonctionnera pour tous ceux qui ont le même problème.

columns = df.columns.to_numpy()
iteration_count = 30
new_df = pd.DataFrame(columns=columns)

for i in range(iteration_count):
    for k in df.iterrows():
        data_obj = {}
        for j in range(columns.size):
            random_index = np.random.randint(0,13, dtype='int')
            data_obj[columns[j]] = df.loc[random_index][columns[j]]
        new_df = new_df.append(data_obj, ignore_index=True)

df = df.append(new_df, ignore_index=True)


0 commentaires