Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 41 drop3 instance selection algorithms #54

Merged
merged 3 commits into from
Jan 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions Instance Selection Algorithms/DROP3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Filename: DROP3.py
# @Author: Daniel Puente Ramírez
# @Time: 31/12/21 16:00

from sys import maxsize

import numpy as np
from sklearn.datasets import load_iris

from ENN import ENN
from graficas import grafica_2D


def with_without(x_sample, sample_associates, samples_labels, neighs):
with_ = 0
without = 0
for a_sample in sample_associates:
a_label = samples_labels[tuple(a_sample)]
for y_sample, y_neighs, y_labels in neighs:
if np.array_equal(a_sample, y_sample):
count = np.bincount(y_labels)
max_class = np.where(count == np.amax(count))[0][0]
if max_class == a_label:
was_in = False
for a_neigh in y_neighs:
if np.array_equal(x_sample, a_neigh):
was_in = True
break
if was_in:
with_ += 1
else:
without += 1
break

return with_, without


def DROP3(X, k):
"""
:param X:
:param k:
:return:
"""
# Filtro de ruido
S = ENN(X, k)

# Ordenar las instancias en S por la distancia a su enemigo más próximo
# de más lejano a más cercano
initial_samples, initial_labels = S['data'], S['target']
initial_distances = []

for x_sample, x_label in zip(initial_samples, initial_labels):
min_distance = maxsize
for y_sample, y_label in zip(initial_samples, initial_labels):
if x_label != y_label:
xy_distance = np.linalg.norm(x_sample - y_sample)
if xy_distance < min_distance:
min_distance = xy_distance
initial_distances.append([x_sample, x_label, min_distance])

initial_distances.sort(key=lambda x: x[2], reverse=True)

# Para cada x en S, encontrar sus k-NN y añadir x a la lista de asociados
# de sus k-NN
sample_neighs = []
sample_associates = [[x, []] for x, _, _ in initial_distances]

for x_sample, _, _ in initial_distances:
y_sample_distance = []
for y_sample, y_label in zip(initial_samples, initial_labels):
if not np.array_equal(x_sample, y_sample):
y_sample_distance.append([y_sample, y_label, np.linalg.norm(
x_sample - y_sample)])
y_sample_distance.sort(key=lambda x: x[2])
x_neighs = [x for x, _, _ in y_sample_distance[:k]]
x_neighs_labels = [x for _, x, _ in y_sample_distance[:k]]
sample_neighs.append([x_sample, x_neighs, x_neighs_labels])

for index, a in enumerate(sample_associates):
a_sample = a[0]
for y_sample, _, _ in y_sample_distance[:k]:
if np.array_equal(a_sample, y_sample):
sample_associates[index][1].append(x_sample)
break

# Para cada x en S calcular with and without
final_samples = [x for x, _, _ in initial_distances]
final_labels = [x for _, x, _ in initial_distances]
samples_labels_dict = {tuple(x): y for x, y, _ in initial_distances}
removed = 0

for index in range(len(initial_distances)):
x_sample, x_label = initial_distances[index][0], initial_distances[
index][1]
x_associates = sample_associates[index]
with_, without = with_without(x_sample, x_associates[1],
samples_labels_dict, sample_neighs)

if without >= with_:
final_samples = np.delete(final_samples, index - removed, axis=0)
final_labels = np.delete(final_labels, index - removed, axis=0)

removed += 1
for associate in x_associates[1]:
for index_y, y in enumerate(sample_neighs):
y_sample, y_neighs, y_neighs_labels = y
if np.array_equal(associate, y_sample):
# Eliminar x de la lista de vecinos de a
for x_index, neigh in enumerate(y_neighs):
if np.array_equal(x_sample, neigh):
break
del y_neighs[x_index]
del y_neighs_labels[x_index]

# Encontrar un nuevo vecino para a
z_distances = []
for z_sample, z_label in zip(final_samples,
final_labels):
if not np.array_equal(associate, z_sample):
z_distance = np.linalg.norm(associate -
z_sample)
z_distances.append([z_sample, z_label,
z_distance])
z_distances.sort(key=lambda x: x[2])

for neigh_sample, neigh_label, _ in z_distances[:k]:
was_in = False
for index_z, old_neigh in enumerate(y_neighs):
if np.array_equal(neigh_sample, old_neigh):
was_in = True
break
if not was_in:
y_neighs.append(neigh_sample)
y_neighs_labels.append(neigh_label)
break
sample_neighs[index_y][1] = y_neighs
sample_neighs[index_y][2] = y_neighs_labels

# Añadir a en la lista de asociados del nuevo vecino
for index_z, z in enumerate(sample_associates):
z_sample, z_associates = z
if np.array_equal(z_sample, neigh_sample):
z_associates.append(associate)
break
sample_associates[index_z][1] = z_associates
break

S['data'] = final_samples
S['target'] = final_labels.tolist()

return S


if __name__ == '__main__':
iris = load_iris()
print(f'Input samples: {len(iris.data)}')
S = DROP3(iris, 3)
print(f'Output samples: {len(S.data)}')
grafica_2D(S)
2 changes: 1 addition & 1 deletion Instance Selection Algorithms/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from CNN import CNN
from ENN import ENN
from ICF_V2 import ICF
from ICF import ICF
from MSS import MSS
from RNN import RNN

Expand Down
13 changes: 12 additions & 1 deletion docs/bibliografia.bib
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,15 @@ @inproceedings{zhou2004democratic
pages={594--602},
year={2004},
organization={IEEE}
}
}

@article{wilson2000reduction,
title={Reduction techniques for instance-based learning algorithms},
author={Wilson, D Randall and Martinez, Tony R},
journal={Machine learning},
volume={38},
number={3},
pages={257--286},
year={2000},
publisher={Springer}
}
Binary file modified docs/memoria.pdf
Binary file not shown.
52 changes: 52 additions & 0 deletions docs/tex/3_Conceptos_teoricos.tex
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,58 @@ \subsubsection{Algoritmos de selección de instancias}\label{subsubsec:Instance-
\end{algorithmic}
\end{algorithm}

\paragraph{\textit{Decremental Reduction Optimization Procedure}}\label{paragraph:DROP}
\hfill \break
Bajo el nombre de \textit{Decremental Reduction Optimization Procedure, DROP}~\cite{wilson2000reduction} nos encontramos con hasta 5 aproximaciones para la resolución del mismo problema. Todas ellas seleccionan prototipos en función de \textit{socio} y \textit{asociado}. Definidos como:
\begin{itemize}
\item Socio. Sea $X \not= \emptyset$, el socio de un objeto $P$ el cual pertence al conjunto $X$, es aquél objeto que tiene a $P$ como uno de sus $k$ vecinos más cercanos.
\item Asociado. Todo prototipo que contenga a $P$ como a uno de sus $k$ vecinos más cercanos, será denominado asociado de $P$, denotado con la expresión $P.A_{1,\dots,a}$ donde $a$ es el número de asociados de $P$.
\end{itemize}

\begin{algorithm}[H]
\caption{Algoritmo \textit{Decremental Reduction Optimization Procedure 3}, \textit{DROP3}.}\label{alg:DROP3}
\begin{algorithmic}[1]
\Require Conjunto de entrenamiento $X$ y número de vecinos más cercanos a considerar, $k$
\Ensure Conjunto editado $S \subset X$
\Statex
\Procedure{DROP3}{$X, k$}
\State $T \leftarrow \text{Filtrado de ruido}(X)$
\State $S \leftarrow T$
\State Ordenar las instancias de $S$ por la distancia a su enemigo más próximo \Comment de mayor a menor
\ForAll{$x \in S$}
\State Encontrar los $x.N_{1\dots k+1}$, los $k+1$ vecniso más cercanos de $x$ en $S$
\State Añadir $x$ a la lista de asociados de cada uno de sus vecinos
\EndFor
\ForAll{$x \in S$}
\State $with \leftarrow$ \# número de asociados de $x$ clasificados correctamente \textbf{con} $x$ como vecino
\State $without \leftarrow$ \# número de asociados de $x$ clasificados correctamente \textbf{sin} $x$ como vecino
\If{$without \geq with$}
\State Eliminar $x$ de $S$
\ForAll{Asociado $a$ de $x$}
\State Eliminar $x$ de la lista de vecinos de $a$
\State Encontrar nuevo vecino para $a$
\State Añadir $a$ en la lista de asociados del nuevo vecino
\EndFor
\EndIf
\EndFor
\State \textbf{return} $S$
\EndProcedure
\end{algorithmic}
\end{algorithm}

Todas las aproximaciones de $DROP\lbrace 1\dots5\rbrace$ se basan en el mismo algoritmo~\cite{wilson2000reduction} pero con modificaciones el las técnicas de pre-procesado de los prototipos. Sus diferencias son:
\begin{itemize}
\item \textit{DROP1}. Eliminará un objeto $P$ de $S$ si sus socios en $S$ se clasifican correctamente sin $P$, i.e. la ausencia de $P$ no impide la correcta clasificación del resto de prototipos.
\item \textit{DROP2}. Eliminará un objeto $P$ de $S$ si los socios que tiene $P$ en $TS$ se clasifican correctamente sin $P$, i.e., verificará el efecto que causa esta eliminación sobre la muestra original. Previo al proceso de eliminación de objetos $P$, ordena los prototipos a tratar en orden a su enemigo más cercano, permitiendo que los primeros prototipos que se van a tratar serán aquellos más alejados de las fronteras de decisión.
\item \textit{DROP3}. Lo primero de todo realiza un filtrado de ruido, muy similar a la edición de Wilson, ver~en~\ref{paragraph:ENN}. Seguidamente aplica el algoritmo \textit{DROP2}, ver algoritmo~\ref{alg:DROP3}
\item \textit{DROP4}. Aplica un filtro de ruido diferente, en este casos consistirá en eliminar un prototipo solo si su eliminación no provoca que alguna otra instancia sea mal clasificada.
\item \textit{DROP5}. Modificación sobre \textit{DROP2}, en este algoritmo el proceso de eliminación de objetos comienza por aquellos más cercanos a sus enemigos.
\end{itemize}

El concepto \textit{with} permite recoger el número de asociados correctamente clasificados teniendo en cuenta un prototipo $x$ como vecino, en cambio \textit{without} tiene en cuenta el número de asociados correctamente clasificados los cuales no tienen el prototipo $x$ como vecino. En los casos en los que $withput > with$ se está tratando con un prototipo el cual no aporta información sobre el conjunto $S$ permitiendo su eliminación.



\vfill
\section{Función distancia entre instancias}
Una función distancia proporciona la proximidad entre dos instancias en función de todos sus parámetros. Si la distancia que separa dos instancias es cero, ambas instancias son idénticas. Se tiende a trabajar con conjuntos de datos normalizados, i.e. todos los datos son ajustados a una escala común, independientemente de la escala en la que hayan sido medidos, para evitar que atributos/características con mucha varianza puedan <<despistar>> a los algoritmos.
Expand Down