我尝试迭代多次时出错

时间:2013-04-04 18:37:40

标签: python

我有这个程序计算IA的k-means

#! /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 

当我为maxit = 2执行此操作时,它会抛出:

  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__'
有人可以帮帮我吗?我今晚必须发送它:(谢谢2全部!!

1 个答案:

答案 0 :(得分:3)

看起来你有一个字典(dic2)的浮点数和浮点字典(dic1)字典,你用这一行拉出一个项目:

comunes = [x for x in dic1 if x in dic2]

然后你试图在这里迭代这个float

media2 = sum([dic2[x][1] for x in comunes]) / nComunes

要解决此问题,请查看dic1dic2及其定义方式。