I've got this program which calculate k-means for IA
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from random import sample
from itertools import repeat
from math import sqrt
# Parametros
k = 6
maxit = 2
def leeValoracionesFiltradas (nomFichero = "valoracionesFiltradas.data"):
lineas = [(l.strip()).split("\t") for l in (open(nomFichero).readlines())]
diccio = {}
for l in lineas:
diccio[int(l[0])] = {}
for l in lineas:
diccio[int(l[0])][int(l[1])] = (float(l[2]),float(l[3]))
return diccio
def distEuclidea(dic1, dic2):
# Se calcula la suma de cuadrados de los elementos comunes a los dos diccionarios
sum2 = sum([pow(dic1[elem]-dic2[elem], 2)
for elem in dic1 if elem in dic2])
return sqrt(sum2)
def similitudEuclidea(dic1, dic2):
return 1/(1+distEuclidea(dic1, dic2))
def coefPearson(dic1, dic2):
# Se consiguen los elementos comunes en ambos diccionarios
comunes = [x for x in dic1 if x in dic2]
nComunes = float(len(comunes))
# Si no hay comunes -> cero
if nComunes==0:
return 0
# Calculo de las medias de cada diccionario
media1 = sum([dic1[x][1] for x in comunes]) / nComunes
media2 = sum([dic2[x][1] for x in comunes]) / nComunes
# Numerador y denominador
num = sum([(dic1[x][1] - media1) * (dic2[x][1] - media2) for x in comunes])
den1 = sqrt(sum([pow(dic1[x][1] - media1, 2) for x in comunes]))
den2 = sqrt(sum([pow(dic2[x][1] - media2, 2) for x in comunes]))
den = den1 * den2
# Caculo del coeficiente
if den==0:
return 0
return num/den
# Dado un diccionario {key1 : {key2 : valor}} calcula el agrupamiento k-means
# con k clusters (grupo), ejecutando maxit iteraciones, con la funcion de similitud especificada
# Retorna una tupla
# -{key1:numero de clusters} con las asignaciones de clusters (a que clusters pertenece cada elemento)
# -[{key2:valores}] una lista con los k centroides (media de los valores para cada clusters)
def kmeans (diccionario, k, maxit, similitud = coefPearson):
# K puntos aleatorios son elegidos como centroides incialmente
# Cada centroide es {key2 : valor}
centroides = [diccionario[x] for x in sample(diccionario.keys(), k)]
# Se asigna cada key1 a un numero de cluster
previo = None
asignacion = {}
# En cada iteracion se asignan puntos a los centroides y se calculan nuevos centroides
for it in range(maxit):
# Se asignan puntos a los centroides mas cercanos
for key1 in diccionario:
similitudes = map(similitud,repeat(diccionario[key1],k), centroides)
asignacion[key1] = similitudes.index(max(similitudes))
# Si no hay cambios en la asignacion, se termina
if previo == asignacion: break
previo = asignacion
# Se recalculan los centroides (se anotan los valores de cada key a cada centroide)
valores = {x : {} for x in range(k)}
contadores = {x : {} for x in range(k)}
for key1 in diccionario:
grupo = asignacion[key1]
for key2 in diccionario[key1]:
if not valores[grupo].has_key(key2):
valores [grupo][key2] = 0
contadores [grupo][key2] = 0
valores [grupo][key2] += diccionario[key1][key2][1]
contadores[grupo][key2] += 1
# Se calculan las medias (nuevos centroides)
centroides = []
for grupo in valores:
centro = {}
for key2 in valores[grupo]:
centro[key2] = round((valores[grupo][key2] / contadores[grupo][key2]),2)
centroides.append(centro)
if None in centroides: break
return (asignacion, centroides)
# Se obtiene el diccionario de valoraciones (las valoraciones ya han sido filtradas)
diccionario = leeValoracionesFiltradas()
# Se obtienen las asignaciones y los centroides con la correlacion de Pearson
tupla = kmeans (diccionario, k, maxit)
asignaciones = tupla[0]
centroids = tupla[1]
print asignaciones
print centroids
And when I execute this for example for maxit = 2, it throws:
File "kmeans_dictio.py", line 46, in coefPearson
media2 = sum([dic2[x][1] for x in comunes]) / nComunes
TypeError: 'float' object has no attribute '__getitem__'
How can I fix this?
It looks like you have a dictionary (dic2) of floats and a dictionary of dictionaries of floats (dic1) that you are pulling an item out of with this line:
comunes = [x for x in dic1 if x in dic2]
Then you are trying to iterate over this float here:
media2 = sum([dic2[x][1] for x in comunes]) / nComunes
To fix this look at dic1 and dic2 and how they are defined.
Related
I have a random graph and I want to check if in this graph the nodes are connected and show which are the strongly connected items, if any
#grafo 1
grafo1=erdosRenyi(5,0.7)
def not_in(x,y):
#RODA VETOR X SOBRE Y
for i in x:
#VERIFICA SE CADA ITEM DE X ESTA EM Y, SE ESTIVE, REMOVE DO Y
if i in y:
y.remove(i)
#RETORNA SO OS ELEMENTOS RESTANTES DE Y
return y
#VETOR TOTAL DE COMPONENTES | NOS VISITADOS | TOTAL TEMPORARIO
tc = []; visitado = []; tot =0;
#EXECUTA SOBRE TODOS OS NOS
for no in grafo1:
#ADICIONA NO ATUAL AOS VISITADOS
visitado.append(no)
print('BUSCANDO PELOS VERTICES DE ', no)
#ADICIONA AO TOTAL TEMPORARIO DE NOS DO COMPONENTE
tot=tot+1
# VERIFICA SE O NO FOI VISITADO E SE ELE NAO POSSUI NOVOS ELEMENTOS PARA SEREM VISITADOS
if no in visitado and len(not_in(visitado, list(grafo1[no]))) == 0:
#CASO POSITIVO, FINALIZA O COMPONENTE
#ADICIONA UM COMPONENTE NOVO COMPONENTE AO VETOR DE COMPONENTES COMO O SEU TOTAL DE NOS
tc = tc+[tot]
#ZERA A VARIAVEL TEMPORARIA DE NOS
tot=0
print("NOVO COMPONENTE\n")
print('\nTOTAL DE COMPONENTES ',len(tc))
print('MAIOR COMPONENTE CONEXO ', max(tc))
print('TAMANHO DE TODOS OS COMPONENTES ', tc)
I'm trying to code tdma. I have a working program for most of the process, but I can't get the results asked.
I'm supposed to get [2,3,-1,4,-2] as a result, but I get : [-0.5120543981481481, -0.1787210648148148, 0.4824421296296296, 0.4879012345679012, -3.7802469135802474].
I've checked one by one the coefficients for each step, and they're good. I think the problem comes from resolve2, but it worked for gauss pivot. It still can be math, but I'm pretty sure it's not.
import numpy as np
A=np.array([[3.,-3.,0,0,0],[2.,8.,4.,0,0],[0,4.,-8.,3.,0],[0,0,-7.,5.,1.],[0,0,0,-1.,3.]])
B0=[-3.,3.,25.,13.,-10.]
B = np.array([B0]).reshape(len(B0),1)
def det(A):
return np.linalg.det(A)
def op_linescal(A,i,x):
n = len(A[0]) # nbre de colonnes de A
for k in range(n):
A[i,k] = x*A[i,k] # la ligne Li devient la ligne x*Li
return A #retourne la nouvelle matrice
def op_linecombi(A,i,j,x):
n = len(A[0]) # nbre de colonnes de A
for k in range(n):
A[i,k] = A[i,k] + x*A[j,k] # la ligne Li devient la ligne Li + x*Lj
return A #retourne la nouvelle matrice
def tdma1(a,b):
ne = A.shape[0] #donne le nombre d'équations donc de ligne
if ne < 3:
return print("On ne peut pas résoudre avec l'algorithme de Thomas")
if det(A) == 0: # vérifie condition pour appliquer Thomas (matrice inversible : det(A) != 0)
return print("On ne peut pas utiliser cet algorithme de Thomas, la matrice A est singulière.")
l = A.copy() #création de la matrice à modifier
b = B.copy()
for i in range(ne):
# print("{}\n{}".format(a,b))
if i == 0 :
x = 1/l[i,i]
op_linescal(l,i,x) # on divise L1 par b1
op_linescal(b,i,x) # reproduction en b
elif i != 0 and i < ne-1: # i = 1,...,N-1
x1 = -l[i,i-1]
op_linecombi(l,i,i-1,x1) # Li => Li - ai*Li-1
op_linecombi(b,i,i-1,x1)
x2 = 1/l[i,i] # où a[i,i] = bi - ai*ci-1
op_linescal(l,i,x2) # Li => Li / (bi')
op_linescal(b,i,x2)
else: # i = N
x1 = -l[i,i-1]
op_linecombi(l,i,i-1,x1) # Li => Li - ai*Li-1
op_linecombi(b,i,i-1,x1)
print('\n',np.round(a,3))
print('\n{}\n'.format(np.round(b,2)))
return a,b
def resolve2(a,b):
"Renvoie la solution du système Ax = b lorsque A est triangulaire supérieure inversible"
n =len(a[0])
x = [0 for i in range(n)]
x[n-1] = b[n-1,0]/a[n-1,n-1]
for i in range(n-2,-1,-1):
s = 0
for j in range(i+1, n):
s = s + a[i,j]*x[j]
x[i] = (b[i,0] - s)/ a[i,i]
return x
def thomas(a, b):
if det(a) == 0: # vérifie condition pour appliquer Gauss
return print("On ne peut pas utiliser Gauss, la matrice A n'est pas inversible.")
a1,b1 = tdma1(a, b)
x = resolve2(a1, b1)
return x
print(thomas(A, B))
I was trying to deeply search for a solution online before posting here, but I couldn't find it. My problem arises during the reading of images in a training of a convolutional neural network. Basically, I decided to create a function creating the in values and the out values out of a series of images. I want to read all the images of the set, but not all at the same time, to avoid running out of memory, so I create the next function:
def readImages(strSet = 'Train', nIni = 1, nFin = 20):
if strSet not in ('Train','Test'):
return None
#
# Inicializamos los arrays de salida: las imágenes y las etiquetas.
arrImages = []
arrLabels = []
#
# Recorremos todos y cada uno de los directorios dentro del set elegido
for strDir in os.listdir(data_dir+'/' + strSet + '/'):
# Nombre de la clase que estamos tratando.
strClass = strDir[strDir.find('-')+1:]
# Número y nombre de los ficheros, por si es menor que el número n indicado.
arrNameFiles = os.listdir(data_dir+'/' + strSet + '/'+strDir)
nFiles = len(os.listdir(data_dir+'/' + strSet + '/'+strDir))
#
# Cogemos los ficheros desde el nIni al nFin. De esta forma nos aseguramos los cogemos todos en cada directorio.
#print('nImagesClase(',strSet,',',strClass,'):',nImagesClase(strSet, strClass))
if (nIni == -1):
# Si el valor es -1, cogemos todas las imágenes del directorio.
listChosenFiles = arrNameFiles
#print('Todos: ', len(listChosenFiles))
else:
if (nImagesClase(strSet, strClass)<nFin):
# Si ya hemos dado la vuelta a todos los ficheros del grupo, los cogemos al azar.
listChosenFiles = random.sample(arrNameFiles, min(nFiles, nFin-nIni))
#print('Fin del directorio ',nFin,'>',nImagesClase(strSet,strClass),': ', len(listChosenFiles))
else:
# Si no, seguimos.
listChosenFiles = arrNameFiles[nIni-1:min(nFin,nImagesClase(strSet, strClass))-1]
#print('Seguimos ',nIni,'-',nFin,': ', len(listChosenFiles))
#
for file in listChosenFiles:
# Lectura del fichero.
image = plt.imread(data_dir+'/'+strSet+'/'+strDir+'/'+file)
#print('Original Shape: ',image.shape)
#plt.imshow(image)
image = cv2.resize(image, (crop_width, crop_height), interpolation=cv2.INTER_NEAREST)
#image = image.reshape((image_height,image_width,num_channels))
#print('Al array de imágenes: ',image.shape)
arrImages.append(image)
# Añadimos etiquetas.
arrLabel = np.zeros(n_classes)
arrLabel[array_classes.index(strClass)] = 1
arrLabels.append(arrLabel)
#
# Recogemos los valores de entrada y salida en arrays.
y = np.array(arrLabels)
X = np.array(arrImages, dtype=np.uint8)
# Una vez terminado el recorrido por todas las imágenes, reordenamos los índices para que no vayan las imágenes en secuendias de la misma clase.
arrIndexes = np.arange(X.shape[0])
np.random.shuffle(arrIndexes)
X = X[arrIndexes]
y = y[arrIndexes]
#
return X, y
To test the behavior of this function I just execute the following line.
X, y = readImages(strSet = 'Train', nIni = 1, nFin = 5)
Which is ok, until the moment nIni and nFin reach some values (101-105, for example). In that moment, I receive the following error:
ValueError Traceback (most recent call last)
<ipython-input-125-8a690256a1fc> in <module>
----> 1 X, y = readImages(strSet = 'Train', nIni = 101, nFin = 105)
<ipython-input-123-9e9ebc660c33> in readImages(strSet, nIni, nFin)
50 # Recogemos los valores de entrada y salida en arrays.
51 y = np.array(arrLabels)
---> 52 X = np.array(arrImages, dtype=np.uint8)
53 # Una vez terminado el recorrido por todas las imágenes, reordenamos los índices para que no vayan las imágenes en secuendias de la misma clase.
54 arrIndexes = np.arange(X.shape[0])
ValueError: could not broadcast input array from shape (28,28,3) into shape (28,28)
I put some print traces in the reading of the images, and everyone of the read images has a shape of (28,28,3), so I don't really understand from where do I have this (28,28) shape pointed out in the error trace.
Do you know what could be the problem? Did you face this problem earlier?
Thanks in advance.
Some of your images have single channels. Use cv2.imread instead of plt.imread
image = cv2.imread(data_dir+'/'+strSet+'/'+strDir+'/'+file)
I am writing a code to solve second-grade equations and it works just well.
However, when I input the following equation:
x^2 + (10^(20) + 10^(-20)) + 1 = 0
(Yes, my input is 10**20 + 10**(-20)
I get:
x1 = 0 x2 = -1e+20
However, it is taking (10^(20) + 10^(-20) as 10e+20 while, if you do the math:
Here is the LaTeX formatted formula:
Which is almost 10^20 but not 10^20.
How can I get the exact result of that operation so I can get the exact value of the equation in x2?
My code is the following:
#===============================Función para obtener los coeficientes===============================
#Se van a anidar dos funciones. Primero la de coeficientes, luego la de la solución de la ecuación.
#Se define una función recursiva para obtener los coeficientes de la ecuación del usuario
def cof():
#Se determina si el coeficiente a introducir es un número o una cadena de operaciones
op = input("Si tu coeficiente es un número introduce 1, si es una cadena de operaciones introduce 2")
#Se compara la entrada del usuario con la opción.
if op == str(1):
#Se le solicita el número
num = input("¿Cuál es tu número?")
#Se comprueba que efectívamente sea un número
try:
#Si la entrada se puede convertir a flotante
float(num)
#Se establece el coeficiente como el valor flotante de la entrada
coef = float(num)
#Se retorna el valor del coeficiente
return coef
#Si no se pudo convertir a flotante...
except ValueError:
#Se le informa al usuario del error
print("No introdujiste un número. Inténtalo de nuevo")
#Se llama a la función de nuevo
return cofa()
#Si el coeficiente es una cadena (como en 10**20 + 10**-20)
elif op == str(2):
#La entrada se establece como la entrada del usuario
entrada = input("Input")
#Se intenta...
try:
#Evaluar la entrada. Si se puede...
eval(entrada)
#El coeficiente se establece como la evaluación de la entrada
coef = eval(entrada)
#Se regresa el coeficiente
return coef
#Si no se pudo establecer como tal...
except:
#Se le informa al usuario
print("No introdujiste una cadena de operaciones válida. Inténtalo de nuevo")
#Se llama a la función de nuevo
return cofa()
#Si no se introdujo ni 1 ni 2 se le informa al usuario
else:
#Se imprime el mensaje
print("No introdujiste n ni c, inténtalo de nuevo")
#Se llama a la función de nuevo
return cof()
#===============================Función para resolver la ecuación===============================
#Resuelve la ecuación
def sol_cuadratica():
#Se pide el valor de a
print("Introduce el coeficiente para a")
#Se llama a cof y se guarda el valor para a
a = cof()
#Se pide b
print("Introduce el coeficiente para b")
#Se llama cof y se guarda b
b = cof()
#Se pide c
print("Introduce el coeficiente para c")
#Se llama cof y se guarda c
c = cof()
#Se le informa al usuario de la ecuación a resolver
print("Vamos a encontrar las raices de la ecuación {}x² + {}x + {} = 0".format(a, b, c))
#Se analiza el discriminante
discriminante = (b**2 - 4*a*c)
#Si el discriminante es menor que cero, las raices son complejas
if discriminante < 0:
#Se le informa al usuario
print("Las raices son imaginarias. Prueba con otros coeficientes.")
#Se llama a la función de nuevo
return sol_cuadratica()
#Si el discriminante es 0, o mayor que cero, se procede a resolver
else:
#Ecuación para x1
x1 = (-b + discriminante**(1/2))/(2*a)
#Ecuación para x2
x2 = (-b - discriminante**(1/2))/(2*a)
#Se imprimen los resultados
print("X1 = " + str(x1))
print("X2 = " + str(x2))
sol_cuadratica()
Ignore the comments, I'm from a Spanish-speaking country.
The limitations of the machine floating point type is the reason why when adding a very small number to a very big number, the small number is just ignored.
This phenomenon is called absorption or cancellation.
With custom floating point objects (like the ones decimal module) you can achieve any precision (computations are slower, because floating point is now emulated, and not relying on the machine FPU capabilities anymore)
From the decimal module docs:
Unlike hardware based binary floating point, the decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for a given problem
This can be achieved by changing the following global parameter decimal.getcontext().prec
import decimal
decimal.getcontext().prec = 41 # min value for the required range
d = decimal.Decimal(10**20)
d2 = decimal.Decimal(10**-20)
now
>>> d+d2
Decimal('100000000000000000000.00000000000000000001')
As suggested in comments, for the small number it's safer to let decimal module handle the division by using power operator on an already existing Decimal object (even if here, the result is the same):
d2 = decimal.Decimal(10)**-20
So you can use decimal.Decimal objects for your computations instead of native floats.
Hello I always get the error "Error: float() argument must be a string or a number, not 'dict_keys'" when running this code. I thought i ran it before without any problem but it seems like now it does not work anymore. Is that possible? And if so, what can I do to get it working again? My problem is within the very last part where I want to graph the time it took to do calculations. But I guess maybe one of the earlier variables isnt defined correctly or something? Appreaciate your help!
Thank you!
from sklearn.linear_model import LinearRegression
import numpy as np
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt #biblioteca de gráficos a partir de listas o arreglos
import time
import threading #para hacer subprocesos
import gc #gc.collect va borrando lo de la memoria
#Definicion de filas y columnas (Parte de arriba)
np.random.seed(42)
n_rows = 100 #número fijo de filas
cols_min = 100 #comienzo numero de columnas
cols_max = 12_800 #máximo de columnas para que salga del loop
timeout = 90 # segundos maximos para correr la iteracion, se puede ir modificando para testeo
#Generaremos funciones para ir llamando
def mult_range(start, end): #Finalidad es que irá duplicando las columnas
val = start
while val <= end:
yield val
val *= 2
#gen_dataset irá generando un conjunto de datos, partiendo de 100 columnas que son las fijadas en la parte de arriba
#la gracia es tener por separado x e y para luego hacer en una linea los gráficos
def gen_dataset(n_rows, n_cols):
y = np.random.rand(n_rows) #crea la matriz y la rellena con el valor de n_rows // las n filas
x = np.random.rand(n_rows, n_cols) #para la matriz n filas m columnas
return x, y
#cromometrará el tiempo de cálculo
def timeit(timeout, n_cols, result, fn, *args, **kwargs):
try:# función que puede llegar a levantar una excepción
#link: para info https://uniwebsidad.com/libros/algoritmos-python/capitulo-12/excepciones
t1 = datetime.now() #valor actual
fn(*args, **kwargs)
t2 = datetime.now() #valor nuevo
delta = t2 - t1 #diferencia
delta_microsecs = delta.seconds * 1_000_000 + delta.microseconds #tiempo que tardará la ejecución
if (delta_microsecs / 1_000_000) < (timeout + 500_000): #condición para que imprima lo que tarda
#irá imprimiendo instantaneamente en la pantalla para saber el tiempo que tarda por cantidad
print(f"for {n_cols} columns it took {delta_microsecs / 1_000_000} seconds")
#imprime para n columnas tarda delta_microsecs de tiempo
result[n_cols] = delta_microsecs #
#else:
# print(f"for {n_cols} columns it took {delta_microsecs / 1_000_000} seconds")
except MemoryError: #cuando se genera la excepción
#en caso de que utilice muchos recursos del pc
print(f"data doesn't fit in memory for {n_cols} columns")
#regresion con sklearn para las x e y
def sklearn_reg(x, y):
reg = LinearRegression()
reg.fit(x, y) #toma los valor x e y ya definidos
#regresion con numpy para las x e y
def np_reg(x, y): #toma los valor x e y ya definidos
# agregar columna de unos
x_ = np.hstack((np.ones((x.shape[0], 1)), x))
# estimador (x'x)^-1 * (x'y)
return np.matmul(np.linalg.inv(np.matmul(x_.T, x_)),np.matmul(x_.T, y))
#regresion con timeout segundos m columnas de inicio, m++ columnas finales
def time_reg(timeout, cols_min, cols_max, reg_fn, square=False): #square es para poner cuando sea X2
timing = {}
threads = []
for n_cols in mult_range(cols_min, cols_max):
try:
gc.collect()
x, y = gen_dataset(n_rows, n_cols)
if square:
x = np.square(x)
thread = threading.Thread(target=timeit, args=(timeout, n_cols, timing, reg_fn, x, y))
thread.start()
for i in range(timeout):
time.sleep(1)
if not thread.is_alive():
break
else:
print(f"for {n_cols} columns it took more than {timeout} seconds")
except MemoryError:
print(f"data doesn't fit in memory for {n_cols} columns")
return timing
def plot_time(timing):
fig = plt.figure(figsize=(10, 10))
plt.plot(timing.keys(), timing.values())
#plt.axis((0, 1_000_000, 0, 1_000_000))
plt.xlabel('time (μs)')
plt.ylabel('columns')
plt.show()
plot_time(time_reg(timeout, cols_min, cols_max, sklearn_reg))
#generar gráfico con el tiempo que demora según cantidad de columnas
plot_time(time_reg(timeout, cols_min, cols_max, np_reg))
#generar gráfico con el tiempo que demora según cantidad de columnas
``