<jupyter_start><jupyter_text>Oversampling Image Data using LLE based SMOTE.  What is Local Linear Embedding (LLE)?It is an is an intuitive approach based on the idea that small enough neighborhoods will represent patches lying along the manifold, which will then be approximately linear. By fitting locally along the manifold and learning the relationships defined by the intrinsic structure of the data, LLE can learn global, non-linear manifold geometries.The main concept behind LLE is that we define data points in terms of their local linear relationships. We define data point \\(xi\\) as a linear combination of its local neighbors, and then we find a lower dimensional embedding that preserves these local linear relationships.  **Input**: Data vectors \\(x1,...,xn∈Rd\\) with parameters \\(k\\) (nearest neighbors) and \\(m\\) (embedding dimension)**Output**: Lower dimensional embedding vectors \\(yi,...,yn∈Rm\\) with \\(m<d\\)Steps:1. Find \\(k\\) nearest neighbors for each \\(xi\\)2. Solve for weights \\(W\\) to reconstruct each \\(xi\\) as a linear combination of neighbors3. Solve for lower dimensional embedding coordinates \\(yi∈Rm\\) that preserve local linear relationships  Now as the algorithm is explained briefly, let us understand that why are we using this with images?* The SMOTE algorithm comes with the assumption that any oversampling ofthe minority class in the original input space isrestricted by an assumption that the local spacebetween any pair of positive data points is positive.However, this strict assumption is not always truewhen the original data is not linearly separable.* In order to relax this assumption, the LLE technique canbe applied to mapping the original data into a newlinearly separable feature space.* Then the SMOTE algorithm oversamples the minority class in the newfeature space instead. A significant advantage of LLEover the other state-of-the-art learning algorithms isthat a new synthetic vector z generated in the newfeature space can be mapped back to the original input.This is so true in case of images as they exist in high dimensions (high resolution).Reference: <NAME>, <NAME>, <NAME> and <NAME>, "Classification of Imbalanced Data by Using the SMOTE Algorithm and Locally Linear Embedding," 2006 8th international Conference on Signal Processing, Beijing, 2006, pp. , doi: 10.1109/ICOSP.2006.345752.<jupyter_code>import os
from tqdm import tqdm
import cv2
import skimage
from skimage.transform import resize
import numpy as np
#mounting the drive to import images
from google.colab import drive
drive.mount('/content/gdrive')<jupyter_output>Mounted at /content/gdrive<jupyter_text>Note: The images being used are very random.<jupyter_code># writing few lines of code to import images
DATA_DIR = '/content/gdrive/My Drive/ Balanced Preprocessed/'
from skimage.color import rgb2gray
# train_dir = "Chest Xray Preprocessed/"
def get_data(folder):
    X= []
    y = []
    for folderName in os.listdir(folder):
        if not folderName.startswith('.'):
            if folderName in ['0']:
                label = 0
            elif folderName in ['1']:
                label = 1
            for image_filename in tqdm(os.listdir(folder + folderName)):
                img_file = cv2.imread(folder + folderName + '/' + image_filename)
                img_file = skimage.transform.resize(img_file, (256,256,1))
                # img_file = cv2.resize(img_file, (256, 256), interpolation = cv2.INTER_LINEAR) 
                img_arr = np.asarray(img_file)
                X.append(img_arr)
                y.append(label)
    X = np.asarray(X)
    y = np.asarray(y)
    return X, y
X, y = get_data(DATA_DIR)
#Installing the smote variants package
#you can find more info here: 
!pip install smote-variants
import smote_variants as sv
oversampler= sv.MulticlassOversampling(sv.LLE_SMOTE())
X_samp, y_samp= oversampler.sample(X.reshape(X.shape[0], -1), y.ravel())
#converting back to the original shape
X_samp = X_samp.reshape(X_samp.shape[0], 256, 256, 1)
#sanity check before going forward
print(X.shape)
print(X_samp.shape)<jupyter_output>(625, 256, 256, 1)
(1000, 256, 256, 1)<jupyter_text>So as you can see above, initially we had 625 images and after oversampling we have got 1000 images. Also, in the below cell we can see that the number of examples pertaining to each class has also changed. Note: We have used the proportion parameter as 1.<jupyter_code>print(np.unique(y, return_counts=True))
print(np.unique(y_samp, return_counts=True))
# Visualizing the base images
from keras.preprocessing.image import array_to_img
b=array_to_img(X[624])
b
#visualising oversampled images 
b=array_to_img(X_samp[700])
b<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08297962648556877, 'fraction_numerical': 0.02037351443123939, 'mean_word_length': 4.150819672131147, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '253676', 'license': 'Apache-2.0', 'n_tokens_mistral': 1430, 'n_tokens_neox': 1309, 'n_words': 565, 'path': 'ML_AI/SMOTE/LLE_SMOTE_images.ipynb', 'repo_name': 'PranavHegde99/OpenOctober', 'size': '4715'}