0

我有这个为 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__'

我怎样才能解决这个问题?

4

1 回答 1

3

看起来您有一个浮点字典 ( dic2) 和一个浮点字典 ( dic1),您正在使用此行从中拉出一个项目:

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

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

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

要解决此问题,请查看它们dic1以及dic2它们是如何定义的。

于 2013-04-04T18:41:20.827 回答