class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, *args, **kwargs): QtWidgets.QMainWindow.__init__(self, *args, **kwargs) self.setupUi(self) #Inicializando botones y esas weas self.threadpool = QThreadPool() self.txtTest.setReadOnly(True) self.txtMejorK.setReadOnly(True) self.lineElementos.setReadOnly(True) self.lineClases.setReadOnly(True) self.labelTest_2.setText(str(30)) self.spinEntrenamiento.setValue(70) self.spinKUsuario.setValue(10) self.groupBox.setEnabled(False) self.radioCirculo.setChecked(True) self.radioCuadrado.setEnabled(False) self.radioElbow.setChecked(True) self.barraProgreso.setEnabled(False) self.btnGraficoMetodo.setEnabled(False) self.checkRejilla.setChecked(True) self.checkRA.setChecked(True) self.checkCelda.setChecked(False) self.lineCelda.setEnabled(False) self.linePuntoX.setText('0') self.linePuntoY.setText('0') self.lineCelda.setText('0.5') self.btnComparacion.setEnabled(False) self.btnComparacion.setText( 'Debe calcular un k óptimo para comparar gráficos') self.lblCargaTexto.hide() rx = QRegExp("[0-9]\.?[0-9]*") validator = QRegExpValidator(rx, self) self.lineCelda.setValidator(validator) rx2 = QRegExp("[+-]?[0-9]*\.[0-9]*") validator2 = QRegExpValidator(rx2, self) self.linePuntoX.setValidator(validator2) self.linePuntoY.setValidator(validator2) self.comboSeparador.addItems([';', ',', 'Tab', 'Espacio']) self.separadores = {',': ',', ';': ';', 'Tab': '\t', 'Espacio': ' '} self.porcentajeEntrenamiento = 70 self.porcentajeTest = 30 self.diccionario = {} self.datos = None self.resultadosTestMetodo = list() self.resultadosTestUsuario = list() #fecha = datetime.datetime.now().strftime("%m/%d/%Y, %H:%M:%S") self.colores = list() self.ladoDeUnCuadrado = 0.5 self.numero_de_divisiones = 70 #El video mostraba ~68 self.kRaiz = 1 self.kMetodo = 1 self.laRaiz = False self.elMetodo = True self.label_2.setText('No se ha seleccionado ningún archivo') self.abrirDataset.clicked.connect(self.abrirArchivo) self.btnTestUsuario.clicked.connect(self.testearModeloUsuario) self.btnGraficoUsuario.clicked.connect(self.graficarUsuario) self.btnTestMetodo.clicked.connect(self.testearModeloMetodo) self.btnGraficoMetodo.clicked.connect(self.graficarMetodo) self.btnPredecirPunto.clicked.connect(self.predecirPunto) self.spinEntrenamiento.valueChanged.connect(self.cambiarPorcentajes) self.radioRaiz.toggled.connect(self.activarRaiz) self.radioElbow.toggled.connect(self.activarMetodo) self.checkCelda.stateChanged.connect(self.verCelda) self.btnComparacion.clicked.connect(self.realizarComparacion) def verCelda(self): self.lineCelda.setEnabled(self.checkCelda.isChecked()) if self.checkCelda.isChecked(): self.lineCelda.setText("0.5") def activarMetodo(self): self.laRaiz = False self.elMetodo = True def activarRaiz(self): self.laRaiz = True self.elMetodo = False def progress_fn(self, n): self.barraProgreso.setValue(n) def execute_this_fn(self, progress_callback): for n in range(0, 5): time.sleep(1) progress_callback.emit(n * 100 / 4) return "Done." def print_output(self, s): print('') def finTestMetodo(self): for resultado in self.resultadosTestMetodo: self.txtMejorK.insertPlainText("Con k = " + str(resultado[0]) + ", la precisión fue de " + "{:.2f}".format(resultado[1]) + "% \n") def finTestUsuario(self): for resultado in self.resultadosTestUsuario: self.txtTest.insertPlainText("Con k = " + str(resultado[0]) + ", la precisión fue de " + "{:.2f}".format(resultado[1]) + "% \n") #☺def recurring_timer(self): #self.counter +=1 #self.l.setText("Counter: %d" % self.counter) def hiloTestearModeloMetodo(self, progress_callback): self.resultadosTestMetodo = list() aciertos = 0 totalElementos = 0 totalDeTests = 10 if self.laRaiz: k = self.kRaiz else: k = self.kMetodo total = len(self.datos.obtenerDatosTest( self.porcentajeEntrenamiento)) * totalDeTests for i in range(1, totalDeTests + 1): self.datos.aleatorizar() puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento( self.porcentajeEntrenamiento) puntosDeTest = self.datos.obtenerDatosTest( self.porcentajeEntrenamiento) for puntoDeTest in puntosDeTest: loskvecinos = vecinos(puntosDeEntrenamiento, puntoDeTest, k) claseDelPunto = prediccion(puntoDeTest, loskvecinos) totalElementos = totalElementos + 1 if (claseDelPunto == puntoDeTest[-1]): aciertos = aciertos + 1 progreso = totalElementos n = int((progreso * 100) / total) progress_callback.emit(n) porcentajeDeAciertos = (aciertos / totalElementos) * 100 self.resultadosTestMetodo.append((k, porcentajeDeAciertos)) def testearModeloMetodo(self): self.txtMejorK.clear() self.txtMejorK.insertPlainText( 'Ordenando aleatoriamente los datos...\n') self.datos.aleatorizar() self.barraProgreso.setValue(0) if self.laRaiz: self.kRaiz = self.calcularKRaiz() self.continuar() else: worker1 = Worker( self.hiloCalcularKElbow ) # Any other args, kwargs are passed to the run function worker1.signals.result.connect(self.print_output) worker1.signals.finished.connect(self.finCalcularKElbow) worker1.signals.finished.connect(self.continuar) worker1.signals.progress.connect(self.progresoCalcularKElbow) self.threadpool.start(worker1) def continuar(self): self.btnGraficoMetodo.setEnabled(True) self.btnComparacion.setEnabled(True) self.btnComparacion.setText('Comparar gráficos') worker = Worker( self.hiloTestearModeloMetodo ) # Any other args, kwargs are passed to the run function worker.signals.result.connect(self.print_output) worker.signals.finished.connect(self.finTestMetodo) worker.signals.progress.connect(self.progress_fn) # Execute self.threadpool.start(worker) def hiloTestearModeloUsuario(self, progress_callback): self.resultadosTestUsuario = list() k = self.obtenerValorDeK() total = k * 10 * len( self.datos.obtenerDatosTest(self.porcentajeEntrenamiento)) progreso = 0 listadedatos = [] for i in range(1, k + 1): listadedatos.append(0) for i in range(1, 11): self.datos.aleatorizar() puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento( self.porcentajeEntrenamiento) puntosDeTest = self.datos.obtenerDatosTest( self.porcentajeEntrenamiento) for puntoDeTest in puntosDeTest: loskvecinos = vecinos(puntosDeEntrenamiento, puntoDeTest, k) for j in range(1, k + 1): progreso = progreso + 1 claseDelPunto = prediccion(puntoDeTest, loskvecinos[0:j]) if (claseDelPunto == puntoDeTest[-1]): listadedatos[j - 1] = listadedatos[j - 1] + 1 n = int((progreso * 100) / total) progress_callback.emit(n) puntosDeTest = self.datos.obtenerDatosTest( self.porcentajeEntrenamiento) for i in range(0, k): listadedatos[i] = (listadedatos[i] / (10 * len(puntosDeTest))) * 100 for i in range(1, k + 1): self.resultadosTestUsuario.append((i, listadedatos[i - 1])) #for resultado in resultados: #self.txtTest.insertPlainText("Con K = " + str(resultado[0]) + ", la eficacia fue de " + "{:.2f}".format(resultado[1]) + "% \n") #TODO: esto no debería pasar porque están en hilos distintos #self.archivo.datosDeEntrenamiento(self.porcentajeEntrenamiento) #pyplot.plot(self.archivo.datosEntrenamientoX,self.archivo.datosEntrenamientoY,'go') #pyplot.show() def testearModeloUsuario(self): self.txtTest.clear() self.barraProgreso.setValue(0) worker = Worker( self.hiloTestearModeloUsuario ) # Any other args, kwargs are passed to the run function worker.signals.result.connect(self.print_output) worker.signals.finished.connect(self.finTestUsuario) worker.signals.progress.connect(self.progress_fn) # Execute self.threadpool.start(worker) def hayUnNumero(self): try: float(self.linePuntoX.text()) float(self.linePuntoY.text()) return True except ValueError: return False def mostrarError(self, tipo, titulo, mensaje, detalles): coso = QMessageBox() if tipo == 'Critical': coso.setIcon(QMessageBox.Critical) else: if tipo == 'Information': coso.setIcon(QMessageBox.Information) coso.setText(mensaje) coso.setInformativeText('') coso.setWindowTitle(titulo) if detalles != '': coso.setDetailedText(detalles) coso.setStandardButtons(QMessageBox.Ok) #coso.buttonClicked.connect(msgbtn) retval = coso.exec_() def predecirPunto(self): self.txtTest.clear() mipunto = list() if self.hayUnNumero(): mipunto.append(float(self.linePuntoX.text())) mipunto.append(float(self.linePuntoY.text())) #puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento(self.porcentajeEntrenamiento) #puntosDeTest = self.datos.obtenerDatosTest(self.porcentajeEntrenamiento) for i in range(1, 11): loskvecinos = vecinos(self.datos.datosCompletos, mipunto, i) #print("Para " + str(i) + " vecinos sus vecinos más cercanos son:") #print(loskvecinos) claseDelPunto = prediccion(mipunto, loskvecinos) #print("La clase predicha fue " + claseDelPunto) self.txtTest.insertPlainText( "Con " + str(i) + " vecinos, la clase predicha fue " + claseDelPunto + "\n") #self.archivo.datosDeEntrenamiento(self.porcentajeEntrenamiento) #pyplot.plot(self.archivo.datosEntrenamientoX,self.archivo.datosEntrenamientoY,'go') #pyplot.show() else: tipo = 'Critical' titulo = 'Error' mensaje = 'No has ingresado un punto válido' detalles = 'Las coordenadas ingresadas no son válidas' self.mostrarError(tipo, titulo, mensaje, detalles) def cambiarPorcentajes(self): self.porcentajeEntrenamiento = self.spinEntrenamiento.value() self.porcentajeTest = 100 - self.spinEntrenamiento.value() self.labelTest_2.setText(str(self.porcentajeTest)) self.btnGraficoMetodo.setEnabled(False) self.btnComparacion.setEnabled(False) self.btnComparacion.setText( 'Debe calcular un k óptimo para comparar gráficos') def cambiarKUsuario(self): self.valorDeK = self.spinKUsuario.value() def abrirArchivo(self): options = QFileDialog.Options() ruta_de_archivo, _ = QFileDialog.getOpenFileName( self, "Abrir Dataset", "", "Archivos de texto (*.txt);; Archivos CSV (*.CSV)", options=options) if ruta_de_archivo: self.label_2.setText(ruta_de_archivo) self.archivo = Archivo(ruta_de_archivo) try: self.archivo.abrir( self.separadores[self.comboSeparador.currentText()]) except: self.label_2.setText("Separadores no válidos") self.groupBox.setEnabled(False) self.barraProgreso.setEnabled(False) tipo = 'Critical' titulo = 'No se ha podido cargar el archivo' mensaje = 'Los separadores de datos escogidos no son válidos para este archivo, pruebe con otro/s' detalles = '' self.mostrarError(tipo, titulo, mensaje, detalles) else: self.groupBox.setEnabled(True) self.barraProgreso.setEnabled(True) self.txtTest.clear() self.txtMejorK.clear() self.valorDeK = 7 #print("datos del archivo") #print(self.archivo.datos) self.datos = Datos() self.datos.atributos = self.archivo.columnas self.datos.generar(deepcopy(self.archivo.datos)) #print("datos del archivo") #print(self.archivo.datos) self.tableWidget.setColumnCount(self.archivo.numcolumnas) self.tableWidget.setRowCount(self.archivo.numfilas) self.tableWidget.setHorizontalHeaderLabels( self.archivo.columnas) self.lineClases.setText(str( self.datos.obtenerNumeroDeClases())) self.lineElementos.setText(str(self.datos.obtenerCantidad())) for fila in range(self.archivo.numfilas): for columna in range(self.archivo.numcolumnas): self.tableWidget.setItem( fila, columna, QTableWidgetItem( (self.archivo.datos[fila][columna]))) else: self.label_2.setText("No se ha seleccionado ningún archivo") self.groupBox.setEnabled(False) self.barraProgreso.setEnabled(False) def obtenerValorDeK(self): return int(self.spinKUsuario.value()) def obtenerMejorK(self): if (self.radioRaiz.isChecked()): return self.calcularKRaiz() else: return self.calcularKElbow() def calcularKRaiz(self): k = int(sqrt(self.datos.obtenerCantidad())) if (((k % 2) == 0) and (((self.datos.obtenerNumeroDeClases()) % 2) == 0)): k = k + 1 return k def finCalcularKElbow(self): self.txtMejorK.insertPlainText("Se ha detectado un k óptimo igual a " + str(self.kMetodo) + "\n ------------- \n") def progresoCalcularKElbow(self, n): self.txtMejorK.insertPlainText('Analizando k = ' + str(n) + "\n") def hiloCalcularKElbow(self, progress_callback): puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento( self.porcentajeEntrenamiento) puntosDeTest = self.datos.obtenerDatosTest( self.porcentajeEntrenamiento) raiz = self.calcularKRaiz() self.resultadosTestMetodo = list() aciertos = 0 totalElementos = 0 k = 1 mejorK = 1 fin = False mejorValor = 0 j = 0 while (not fin): progress_callback.emit(k) aciertos = 0 totalElementos = 0 for puntoDeTest in puntosDeTest: loskvecinos = vecinos(puntosDeEntrenamiento, puntoDeTest, k) claseDelPunto = prediccion(puntoDeTest, loskvecinos) totalElementos = totalElementos + 1 if (claseDelPunto == puntoDeTest[-1]): aciertos = aciertos + 1 porcentajeDeAciertos = (aciertos / totalElementos) * 100 self.resultadosTestMetodo.append((k, porcentajeDeAciertos)) #¹print('k' + str(k) + 'j' + str(j) + 'raiz' + str(raiz)) if (porcentajeDeAciertos > mejorValor): mejorValor = porcentajeDeAciertos mejorK = k j = 0 else: j = j + 1 if ((j > (raiz / 2)) or (k > raiz)): fin = True else: k = k + 1 #for resultado in resultados: #self.txtMejorK.insertPlainText("Con K = " + str(resultado[0]) + ", la eficacia fue de " + "{:.2f}".format(resultado[1]) + "% \n") self.kMetodo = mejorK def obtenerRejilla(self): return (self.checkRejilla.isChecked()) def obtenerRA(self): if self.checkRA.isChecked(): return True else: return False return (self.checkRejilla.isChecked()) def obtenerCelda(self): if (self.checkCelda.isChecked() and (0 < float(self.lineCelda.text()))): return float(self.lineCelda.text()) else: return 0.5 def insertarCirculos(self, grafico, ejes, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, salto): cuadrados = [] x = limiteInferiorX y = limiteInferiorY xDePrueba = x + salto / 2 yDePrueba = y + salto / 2 while (y < limiteSuperiorY): x = limiteInferiorX xDePrueba = x + salto / 2 while (x < limiteSuperiorX): clase = (predecirClaseConCalidad(self.datos.datosCompletos, (xDePrueba, yDePrueba), k))[0] calidad = (predecirClaseConCalidad(self.datos.datosCompletos, (xDePrueba, yDePrueba), k))[1] calidad = ((salto / 2) * (calidad)) color = self.diccionario[clase] cuadrado = mpatches.Circle((x + (salto / 2), y + (salto / 2)), radius=calidad, color=color, alpha=0.4, linewidth=0) #grafico.patches.extend([pyplot.Rectangle((x,y),saltoDelCuadrado,saltoDelCuadrado, #fill=True, color=color, alpha=0.5, zorder=1000, #transform=grafico.transFigure, figure=grafico)]) cuadrados.append(cuadrado) ejes.add_patch(cuadrado) x = x + salto xDePrueba = x + salto / 2 y = y + salto yDePrueba = y + salto / 2 #for c in cuadrados: #print(str(c) + "/n") def graficarMetodo(self): if self.laRaiz: k = self.kRaiz mensaje = 'Raiz' else: k = self.kMetodo mensaje = 'Codo' self.graficarDataset(k, mensaje, False) def graficarUsuario(self): k = self.obtenerValorDeK() self.graficarDataset(k, 'Usuario', False) def realizarComparacion(self): self.lblCargaTexto.show() tipo = 'Information' titulo = 'Aviso' mensaje = 'Esta operación podría tardar. Por favor espere...' detalles = '' self.mostrarError(tipo, titulo, mensaje, detalles) kUsuario = self.obtenerValorDeK() if self.laRaiz: kMetodo = self.kRaiz metodo = 'Raiz' else: kMetodo = self.kMetodo metodo = 'Codo' for k in range(1, kUsuario + 1): self.graficarDataset(k, 'Usuario', True) self.graficarDataset(kMetodo, metodo, True) self.ventanaComparacion = Grids(kUsuario, kMetodo) self.ventanaComparacion.show() self.lblCargaTexto.hide() def graficarDataset(self, k, tipoDeGrafico, imprimir): valorDeSeparacionX = (self.datos.maxX() - self.datos.minX()) * 0.1 valorDeSeparacionY = (self.datos.maxY() - self.datos.minY()) * 0.1 limiteInferiorX = self.datos.minX() - valorDeSeparacionX limiteSuperiorX = self.datos.maxX() + valorDeSeparacionX limiteInferiorY = self.datos.minY() - valorDeSeparacionY limiteSuperiorY = self.datos.maxY() + valorDeSeparacionY pyplot.clf() grafico = pyplot.figure(figsize=(8, 8)) ax = grafico.add_subplot() ax.plot(limiteInferiorX, limiteInferiorY) if self.obtenerRA(): ax.set_aspect(1) #if(len(self.datos.clases)>9): #self.colores = colors.CSS4_COLORS #else: #self.colores = colors.TABLEAU_COLORS self.colores = colors.TABLEAU_COLORS #divisionX = (self.datos.maxX() + valorDeSeparacionX - self.datos.minX() + valorDeSeparacionY) / (self.numero_de_divisiones) #divisionY = (self.datos.maxY() + valorDeSeparacionY - self.datos.minY() + valorDeSeparacionY) / (self.numero_de_divisiones) #print(divisionX) limiteCeldaX = (trunc( ((limiteSuperiorX - limiteInferiorX) / self.obtenerCelda())) + 1) * self.obtenerCelda() + limiteInferiorX limiteCeldaY = (trunc( ((limiteSuperiorY - limiteInferiorY) / self.obtenerCelda())) + 1) * self.obtenerCelda() + limiteInferiorY pyplot.xlim(limiteInferiorX, limiteCeldaX) pyplot.ylim(limiteInferiorY, limiteCeldaY) pyplot.xlabel(self.datos.atributos[0]) pyplot.ylabel(self.datos.atributos[1]) xDelBucle = limiteInferiorX yDelBucle = limiteInferiorY if (self.obtenerRejilla()): while (xDelBucle < limiteSuperiorX): pyplot.axvline(x=xDelBucle, linestyle='-', marker=",", linewidth=0.2) xDelBucle = xDelBucle + self.obtenerCelda() while (yDelBucle < limiteSuperiorY): pyplot.axhline(y=yDelBucle, linestyle='-', marker=",", linewidth=0.2) yDelBucle = yDelBucle + self.obtenerCelda() self.diccionario = {} i = 0 lista = list(self.colores.items()) for clase in self.datos.clases: self.diccionario[clase] = lista[i][0] i = i + 1 puntos = self.datos.datosCompletos #ËpuntosEntrenamiento = self.datos.obtenerDatosEntrenamiento(self.porcentajeEntrenamiento) for punto in puntos: #puntosEntrenamiento: pyplot.plot(punto[0], punto[1], marker='o', color=self.diccionario[punto[2]]) leyendas = [] for clase in self.datos.clases: leyendas.append( Line2D([0], [0], lw=4, marker='o', color=self.diccionario[clase])) pyplot.legend(leyendas, self.datos.clases, loc='upper left') #print(self.colores) #print(lista) #print(self.diccionario) self.gridcolores = [] self.gridclases = {} self.gridcolores.append('#FFFFFF') i = 1 for clase in self.datos.clases: self.gridclases[clase] = i self.gridcolores.append(self.diccionario[clase]) i = i + 1 #print(self.gridclases) #print(self.gridcolores) inicio = time.time() if (self.radioCuadrado.isChecked() == True): self.insertarGridV2(grafico, ax, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, self.obtenerCelda()) else: self.insertarArray(pyplot, grafico, ax, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, self.obtenerCelda()) #self.insertarCirculos(grafico,ax,limiteInferiorX,limiteSuperiorX,limiteInferiorY,limiteSuperiorY,k,self.obtenerCelda()) fin = time.time() #print(fin-inicio) if tipoDeGrafico == 'Usuario': nombre = tipoDeGrafico + str(k) else: nombre = 'Metodo' if tipoDeGrafico == 'Raiz': mensaje = 'Utilizando método de la Raíz con k = ' else: if tipoDeGrafico == 'Codo': mensaje = 'Utilizando método del codo con k = ' else: mensaje = 'Rango de K ingresado por el usuario, k = ' mensaje = mensaje + str(k) pyplot.title(mensaje) if imprimir: grafico.savefig(nombre) else: grafico.show() def insertarArray(self, elpyplot, grafico, ejes, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, salto): cuadrados = [] x = limiteInferiorX y = limiteInferiorY yDePrueba = y + salto / 2 arreglo = [] while (y < limiteSuperiorY): fila = [] x = limiteInferiorX xDePrueba = x + salto / 2 while (x < limiteSuperiorX): clases = [] clase1 = predecirClase(self.datos.datosCompletos, (xDePrueba - (salto / 2), yDePrueba - (salto / 2)), k) clases.append(clase1) clase2 = predecirClase(self.datos.datosCompletos, (xDePrueba - (salto / 2), yDePrueba + (salto / 2)), k) clases.append(clase2) clase3 = predecirClase(self.datos.datosCompletos, (xDePrueba + (salto / 2), yDePrueba - (salto / 2)), k) clases.append(clase3) clase4 = predecirClase(self.datos.datosCompletos, (xDePrueba + (salto / 2), yDePrueba + (salto / 2)), k) clases.append(clase4) contadores = Counter(clases) clase = masFrecuente(clases) calidad = contadores[clase] if calidad < 3: fila.append(0) else: fila.append(self.gridclases[clase]) #cuadrado = mpatches.Rectangle((x,y),salto,salto,angle = 0.0,color=color, alpha=(0.5*proporcion),linewidth=0) #cuadrados.append(cuadrado) #ejes.add_patch(cuadrado) x = x + salto xDePrueba = x + salto / 2 arreglo.append(fila) y = y + salto yDePrueba = y + salto / 2 nuevoarreglo = np.array(arreglo) #print(len(nuevoarreglo)*len(nuevoarreglo[0])) #print(len(arreglo)) #print(len(nuevoarreglo)) # Setup a mesh grid and values step = salto # mesh step size xx, yy = np.meshgrid( np.arange(limiteInferiorX, limiteSuperiorX + salto, step), np.arange(limiteInferiorY, limiteSuperiorY + salto, step)) z = nuevoarreglo #np.random.randint(0, 3, xx.shape) # random integers in [0, 2] lista = list(self.colores.items()) cmap = ListedColormap(self.gridcolores) # color map for [0, 2] elpyplot.pcolormesh(xx, yy, z, cmap=cmap, alpha=0.33) # Plot colorbar for color mesh #cbar = elpyplot.colorbar() #cbar.set_ticks([0.33, 1., 1.67]) def insertarGridV2(self, grafico, ejes, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, salto): cuadrados = [] x = limiteInferiorX y = limiteInferiorY #xDePrueba = x + salto/2 yDePrueba = y + salto / 2 while (y < limiteSuperiorY): x = limiteInferiorX xDePrueba = x + salto / 2 while (x < limiteSuperiorX): clases = [] clase1 = predecirClase(self.datos.datosCompletos, (xDePrueba - (salto / 2), yDePrueba - (salto / 2)), k) clases.append(clase1) clase2 = predecirClase(self.datos.datosCompletos, (xDePrueba - (salto / 2), yDePrueba + (salto / 2)), k) clases.append(clase2) clase3 = predecirClase(self.datos.datosCompletos, (xDePrueba + (salto / 2), yDePrueba - (salto / 2)), k) clases.append(clase3) clase4 = predecirClase(self.datos.datosCompletos, (xDePrueba + (salto / 2), yDePrueba + (salto / 2)), k) clases.append(clase4) contadores = Counter(clases) clase = masFrecuente(clases) calidad = contadores[clase] if calidad == 1: proporcion = 0.0 else: if calidad == 2: proporcion = 0.1 else: if calidad == 3: proporcion = 0.5 else: proporcion = 1 color = self.diccionario[clase] cuadrado = mpatches.Rectangle((x, y), salto, salto, angle=0.0, color=color, alpha=(0.5 * proporcion), linewidth=0) cuadrados.append(cuadrado) ejes.add_patch(cuadrado) x = x + salto xDePrueba = x + salto / 2 y = y + salto yDePrueba = y + salto / 2
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, *args, **kwargs): QtWidgets.QMainWindow.__init__(self, *args, **kwargs) self.setupUi(self) #Inicializando botones y esas weas self.threadpool = QThreadPool() self.txtTest.setReadOnly(True) self.txtMejorK.setReadOnly(True) self.lineElementos.setReadOnly(True) self.lineClases.setReadOnly(True) self.labelTest_2.setText(str(30)) self.spinEntrenamiento.setValue(70) self.spinKUsuario.setValue(10) self.groupBox.setEnabled(False) self.radioCuadrado.setChecked(True) self.radioElbow.setChecked(True) self.btnDetener.setEnabled(False) self.barraProgreso.setEnabled(False) self.comboSeparador.addItems([';', ',', 'Tab', 'Espacio']) self.separadores = {',': ',', ';': ';', 'Tab': '\t', 'Espacio': ' '} self.porcentajeEntrenamiento = 70 self.porcentajeTest = 30 self.diccionario = {} self.datos = None self.resultadosTestMetodo = list() self.resultadosTestUsuario = list() #fecha = datetime.datetime.now().strftime("%m/%d/%Y, %H:%M:%S") self.colores = list() self.ladoDeUnCuadrado = 0.5 self.numero_de_divisiones = 70 #El video mostraba ~68 self.kDeTest = 1 self.label_2.setText('No se ha seleccionado ningún archivo') self.abrirDataset.clicked.connect(self.abrirArchivo) self.btnTestUsuario.clicked.connect(self.testearModeloUsuario) self.btnGraficoUsuario.clicked.connect(self.graficarUsuario) self.btnTestMetodo.clicked.connect(self.testearModeloMetodo) self.btnGraficoMetodo.clicked.connect(self.graficarMetodo) self.btnPredecirPunto.clicked.connect(self.predecirPunto) self.spinEntrenamiento.valueChanged.connect(self.cambiarPorcentajes) #Inicializar widgets def progress_fn(self, n): self.barraProgreso.setValue(n) def execute_this_fn(self, progress_callback): for n in range(0, 5): time.sleep(1) progress_callback.emit(n * 100 / 4) return "Done." def print_output(self, s): print('') def finTestMetodo(self): for resultado in self.resultadosTestMetodo: self.txtMejorK.insertPlainText("Con K = " + str(resultado[0]) + ", la eficacia fue de " + "{:.2f}".format(resultado[1]) + "% \n") def finTestUsuario(self): for resultado in self.resultadosTestUsuario: self.txtTest.insertPlainText("Con K = " + str(resultado[0]) + ", la eficacia fue de " + "{:.2f}".format(resultado[1]) + "% \n") #☺def recurring_timer(self): #self.counter +=1 #self.l.setText("Counter: %d" % self.counter) def hiloTestearModeloMetodo(self, progress_callback): puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento( self.porcentajeEntrenamiento) puntosDeTest = self.datos.obtenerDatosTest( self.porcentajeEntrenamiento) self.resultadosTestMetodo = list() aciertos = 0 totalElementos = 0 k = self.kDeTest total = len(puntosDeTest) for puntoDeTest in puntosDeTest: loskvecinos = vecinos(puntosDeEntrenamiento, puntoDeTest, k) claseDelPunto = prediccion(puntoDeTest, loskvecinos) totalElementos = totalElementos + 1 if (claseDelPunto == puntoDeTest[-1]): aciertos = aciertos + 1 progreso = totalElementos n = int((progreso * 100) / total) progress_callback.emit(n) porcentajeDeAciertos = (aciertos / totalElementos) * 100 self.resultadosTestMetodo.append((k, porcentajeDeAciertos)) def testearModeloMetodo(self): self.txtMejorK.clear() self.barraProgreso.setValue(0) self.kDeTest = self.obtenerMejorK() worker = Worker( self.hiloTestearModeloMetodo ) # Any other args, kwargs are passed to the run function worker.signals.result.connect(self.print_output) worker.signals.finished.connect(self.finTestMetodo) worker.signals.progress.connect(self.progress_fn) # Execute self.threadpool.start(worker) def hiloTestearModeloUsuario(self, progress_callback): puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento( self.porcentajeEntrenamiento) puntosDeTest = self.datos.obtenerDatosTest( self.porcentajeEntrenamiento) self.resultadosTestUsuario = list() k = self.obtenerValorDeK() + 1 for i in range(1, k + 1): aciertos = 0 totalElementos = 0 #TODO: mostrar en una tabla los resultados, por ejemplo #clasesPredichas = list() #clasesReales = list() for puntoDeTest in puntosDeTest: loskvecinos = vecinos(puntosDeEntrenamiento, puntoDeTest, i) claseDelPunto = prediccion(puntoDeTest, loskvecinos) totalElementos = totalElementos + 1 if (claseDelPunto == puntoDeTest[-1]): aciertos = aciertos + 1 porcentajeDeAciertos = (aciertos / totalElementos) * 100 self.resultadosTestUsuario.append((i, porcentajeDeAciertos)) #self.progress_fn(i,k) n = int((i * 100) / k) progress_callback.emit(n) #for resultado in resultados: #self.txtTest.insertPlainText("Con K = " + str(resultado[0]) + ", la eficacia fue de " + "{:.2f}".format(resultado[1]) + "% \n") #TODO: esto no debería pasar porque están en hilos distintos #self.archivo.datosDeEntrenamiento(self.porcentajeEntrenamiento) #pyplot.plot(self.archivo.datosEntrenamientoX,self.archivo.datosEntrenamientoY,'go') #pyplot.show() def testearModeloUsuario(self): self.txtTest.clear() self.barraProgreso.setValue(0) worker = Worker( self.hiloTestearModeloUsuario ) # Any other args, kwargs are passed to the run function worker.signals.result.connect(self.print_output) worker.signals.finished.connect(self.finTestUsuario) worker.signals.progress.connect(self.progress_fn) # Execute self.threadpool.start(worker) def predecirPunto(self): self.txtTest.clear() mipunto = list() mipunto.append(float(self.linePuntoX.text())) mipunto.append(float(self.linePuntoY.text())) #puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento(self.porcentajeEntrenamiento) #puntosDeTest = self.datos.obtenerDatosTest(self.porcentajeEntrenamiento) for i in range(1, 11): loskvecinos = vecinos(self.datos.datosCompletos, mipunto, i) #print("Para " + str(i) + " vecinos sus vecinos más cercanos son:") #print(loskvecinos) claseDelPunto = prediccion(mipunto, loskvecinos) #print("La clase predicha fue " + claseDelPunto) self.txtTest.insertPlainText("Con " + str(i) + " vecinos, la clase predicha fue " + claseDelPunto + "\n") #self.archivo.datosDeEntrenamiento(self.porcentajeEntrenamiento) #pyplot.plot(self.archivo.datosEntrenamientoX,self.archivo.datosEntrenamientoY,'go') #pyplot.show() def cambiarPorcentajes(self): self.porcentajeEntrenamiento = self.spinEntrenamiento.value() self.porcentajeTest = 100 - self.spinEntrenamiento.value() self.labelTest_2.setText(str(self.porcentajeTest)) def cambiarKUsuario(self): self.valorDeK = self.spinKUsuario.value() def abrirArchivo(self): options = QFileDialog.Options() ruta_de_archivo, _ = QFileDialog.getOpenFileName( self, "Abrir Dataset", "", "Archivos de texto (*.txt);; Archivos CSV (*.CSV)", options=options) if ruta_de_archivo: self.label_2.setText(ruta_de_archivo) self.archivo = Archivo(ruta_de_archivo) self.archivo.abrir( self.separadores[self.comboSeparador.currentText()]) self.groupBox.setEnabled(True) self.btnDetener.setEnabled(True) self.barraProgreso.setEnabled(True) self.txtTest.clear() self.txtMejorK.clear() self.valorDeK = 7 #print("datos del archivo") #print(self.archivo.datos) self.datos = Datos() self.datos.generar(deepcopy(self.archivo.datos)) #print("datos del archivo") #print(self.archivo.datos) self.tableWidget.setColumnCount(self.archivo.numcolumnas) self.tableWidget.setRowCount(self.archivo.numfilas) self.tableWidget.setHorizontalHeaderLabels(self.archivo.columnas) self.lineClases.setText(str(self.datos.obtenerNumeroDeClases())) self.lineElementos.setText(str(self.datos.obtenerCantidad())) for fila in range(self.archivo.numfilas): for columna in range(self.archivo.numcolumnas): self.tableWidget.setItem( fila, columna, QTableWidgetItem((self.archivo.datos[fila][columna]))) else: self.label_2.setText("No se ha seleccionado ningún archivo") self.groupBox.setEnabled(False) self.btnDetener.setEnabled(False) self.barraProgreso.setEnabled(False) def obtenerValorDeK(self): return int(self.spinKUsuario.value()) def obtenerMejorK(self): if (self.radioRaiz.isChecked()): return self.calcularKRaiz() else: return self.calcularKElbow() def calcularKRaiz(self): k = int(sqrt(self.datos.obtenerCantidad())) if (((k % 2) == 0) and (((self.datos.obtenerNumeroDeClases()) % 2) == 0)): k = k + 1 return k def finCalcularKElbow(self): self.txtMejorK.insertPlainText("Se ha detectado un k óptimo igual a " + str(self.kDeTest) + "\n ------------- \n") def progresoCalcularKElbow(self, n): self.txtMejorK.insertPlainText('Analizando K = ' + str(n) + "\n") def calcularKElbow(self): self.txtMejorK.clear() worker = Worker( self.hiloCalcularKElbow ) # Any other args, kwargs are passed to the run function worker.signals.result.connect(self.print_output) worker.signals.finished.connect(self.finCalcularKElbow) worker.signals.progress.connect(self.progresoCalcularKElbow) # Execute self.threadpool.start(worker) def hiloCalcularKElbow(self, progress_callback): puntosDeEntrenamiento = self.datos.obtenerDatosEntrenamiento( self.porcentajeEntrenamiento) puntosDeTest = self.datos.obtenerDatosTest( self.porcentajeEntrenamiento) self.resultadosTestMetodo = list() aciertos = 0 totalElementos = 0 k = 1 mejorK = 1 fin = False mejorValor = 0 j = 0 while (not fin): progress_callback.emit(k) aciertos = 0 totalElementos = 0 for puntoDeTest in puntosDeTest: loskvecinos = vecinos(puntosDeEntrenamiento, puntoDeTest, k) claseDelPunto = prediccion(puntoDeTest, loskvecinos) totalElementos = totalElementos + 1 if (claseDelPunto == puntoDeTest[-1]): aciertos = aciertos + 1 porcentajeDeAciertos = (aciertos / totalElementos) * 100 self.resultadosTestMetodo.append((k, porcentajeDeAciertos)) if (porcentajeDeAciertos > mejorValor): mejorValor = porcentajeDeAciertos mejorK = k j = 0 else: j = j + 1 if ((j > 10) or (porcentajeDeAciertos == 100) or (k > 30)): fin = True else: k = k + 1 #for resultado in resultados: #self.txtMejorK.insertPlainText("Con K = " + str(resultado[0]) + ", la eficacia fue de " + "{:.2f}".format(resultado[1]) + "% \n") self.kDeTest = mejorK return mejorK def obtenerRejilla(self): return (self.checkRejilla.isChecked()) def insertarGrid(self, grafico, ejes, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, salto): #¶coordenadas = list() cuadrados = [] x = limiteInferiorX y = limiteInferiorY random.seed(datetime.datetime.now()) xDePrueba = x + self.ladoDeUnCuadrado / 2 yDePrueba = y + self.ladoDeUnCuadrado / 2 while (y < limiteSuperiorY): x = limiteInferiorX xDePrueba = x + self.ladoDeUnCuadrado / 2 while (x < limiteSuperiorX): clase = predecirClase(self.datos.datosCompletos, (xDePrueba, yDePrueba), k) color = self.diccionario[clase] cuadrado = mpatches.Rectangle((x, y), self.ladoDeUnCuadrado, self.ladoDeUnCuadrado, angle=0.0, color=color, alpha=0.4, linewidth=0) #grafico.patches.extend([pyplot.Rectangle((x,y),saltoDelCuadrado,saltoDelCuadrado, #fill=True, color=color, alpha=0.5, zorder=1000, #transform=grafico.transFigure, figure=grafico)]) cuadrados.append(cuadrado) ejes.add_patch(cuadrado) x = x + self.ladoDeUnCuadrado xDePrueba = x + self.ladoDeUnCuadrado / 2 y = y + self.ladoDeUnCuadrado yDePrueba = y + self.ladoDeUnCuadrado / 2 #for c in cuadrados: #print(str(c) + "/n") def insertarCirculos(self, grafico, ejes, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, salto): #coordenadas = list() cuadrados = [] x = limiteInferiorX y = limiteInferiorY random.seed(datetime.datetime.now()) xDePrueba = x + self.ladoDeUnCuadrado / 2 yDePrueba = y + self.ladoDeUnCuadrado / 2 while (y < limiteSuperiorY): x = limiteInferiorX xDePrueba = x + self.ladoDeUnCuadrado / 2 while (x < limiteSuperiorX): clase = (predecirClaseConCalidad(self.datos.datosCompletos, (xDePrueba, yDePrueba), k))[0] calidad = (predecirClaseConCalidad(self.datos.datosCompletos, (xDePrueba, yDePrueba), k))[1] calidad = ((self.ladoDeUnCuadrado / 2) * (calidad)) color = self.diccionario[clase] cuadrado = mpatches.Circle( (x + (self.ladoDeUnCuadrado / 2), y + (self.ladoDeUnCuadrado / 2)), radius=calidad, color=color, alpha=0.4, linewidth=0) #grafico.patches.extend([pyplot.Rectangle((x,y),saltoDelCuadrado,saltoDelCuadrado, #fill=True, color=color, alpha=0.5, zorder=1000, #transform=grafico.transFigure, figure=grafico)]) cuadrados.append(cuadrado) ejes.add_patch(cuadrado) x = x + self.ladoDeUnCuadrado xDePrueba = x + self.ladoDeUnCuadrado / 2 y = y + self.ladoDeUnCuadrado yDePrueba = y + self.ladoDeUnCuadrado / 2 #for c in cuadrados: #print(str(c) + "/n") def graficarMetodo(self): k = self.obtenerMejorK() self.graficarDataset(k) def graficarUsuario(self): k = self.obtenerValorDeK() self.graficarDataset(k) def graficarDataset(self, k): valorDeSeparacionX = (self.datos.maxX() - self.datos.minX()) * 0.1 valorDeSeparacionY = (self.datos.maxY() - self.datos.minY()) * 0.1 limiteInferiorX = self.datos.minX() - valorDeSeparacionX limiteSuperiorX = self.datos.maxX() + valorDeSeparacionX limiteInferiorY = self.datos.minY() - valorDeSeparacionY limiteSuperiorY = self.datos.maxY() + valorDeSeparacionY pyplot.clf() grafico = pyplot.figure(figsize=(8, 8)) ax = grafico.add_subplot() ax.plot(limiteInferiorX, limiteInferiorY) ax.set_aspect(1) if (len(self.datos.clases) > 9): self.colores = colors.CSS4_COLORS else: self.colores = colors.TABLEAU_COLORS #divisionX = (self.datos.maxX() + valorDeSeparacionX - self.datos.minX() + valorDeSeparacionY) / (self.numero_de_divisiones) #divisionY = (self.datos.maxY() + valorDeSeparacionY - self.datos.minY() + valorDeSeparacionY) / (self.numero_de_divisiones) #print(divisionX) pyplot.xlim(limiteInferiorX, limiteSuperiorX) pyplot.ylim(limiteInferiorY, limiteSuperiorY) xDelBucle = limiteInferiorX yDelBucle = limiteInferiorY if (self.obtenerRejilla()): while (xDelBucle < limiteSuperiorX): pyplot.axvline(x=xDelBucle, linestyle='-', marker=",", linewidth=0.2) xDelBucle = xDelBucle + self.ladoDeUnCuadrado while (yDelBucle < limiteSuperiorY): pyplot.axhline(y=yDelBucle, linestyle='-', marker=",", linewidth=0.2) yDelBucle = yDelBucle + self.ladoDeUnCuadrado self.diccionario = {} i = 0 lista = list(self.colores.items()) for clase in self.datos.clases: self.diccionario[clase] = lista[i][0] i = i + 1 for punto in self.datos.datosCompletos: pyplot.plot(punto[0], punto[1], marker='.', color=self.diccionario[punto[2]]) if (self.radioCuadrado.isChecked() == True): self.insertarGrid(grafico, ax, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, self.ladoDeUnCuadrado) else: self.insertarCirculos(grafico, ax, limiteInferiorX, limiteSuperiorX, limiteInferiorY, limiteSuperiorY, k, self.ladoDeUnCuadrado) #Crear cuadrados grafico.show()