군집을 덴드로그램으로 보면 더 명확하게 해석할 수 있다. 계층적 군집화 결과는 대개 이런 식으로 보여지는데, 덴드로그램은 비교적 작은 공간에 많은 정보를 담고 있기 때문이다. 덴드로그램은 그래픽으로 표시되고 JPG로 저장되므로 http://pythonware.com에서 사용할 수 있는 Python Imaging Library(PIL)를 다운로드하십시오.


이 라이브러리에는 Windows용 설치 프로그램 및 다른 플랫폼용 소스 배포가 함께 제공된다. PIL 다운로드 및 설치에 대한 자세한 내용은 부록 A를 참조하십시오. PIL을 사용하면 텍스트와 선으로 이미지를 쉽게 생성할 수 있으며, 덴드로그램만 만들면 된다. 


from PIL import Image,ImageDraw


첫 번째 단계는 주어진 클러스터의 총 높이를 반환하는 기능을 사용하는 것이다. 이미지의 전체 높이와 다양한 노드의 위치를 결정할 때, 그 총 높이를 알아야 한다. 이 클러스터가 끝점(즉, 분기 없음)인 경우, 그 높이는 1이고, 그렇지 않으면 그 가지 높이의 합이다. 


def getheight(clust):

 # Is this an endpoint? Then the height is just 1

 if clust.left==None and clust.right==None: return 1

 # Otherwise the height is the same of the heights of

 # each branch

 return getheight(clust.left)+getheight(clust.right)


또 하나 알아야 할 것은 루트 노드의 총 오류다. 선 길이는 각 노드에서 오차의 양으로 조정되므로 총 오차의 양에 따라 스케일링 계수를 생성하게 된다. 노드의 오류 깊이는 각 분기에서 발생할 수 있는 최대 오류일 뿐이다.


def getdepth(clust):

 # The distance of an endpoint is 0.0

 if clust.left==None and clust.right==None: return 0


drawdendrogram 함수는 각 최종 클러스터에 대해 20픽셀의 높이와 고정 폭을 허용하는 새로운 이미지를 생성한다. 스케일링 계수는 고정 폭을 총 깊이로 나누어 결정한다. 이 함수는 이 이미지에 대한 그리기 객체를 생성한 다음 루트 노드에서 드로잉된 객체를 호출하여 해당 위치가 이미지의 왼쪽 절반 아래에 있어야 함을 알려준다.


def drawdendrogram(clust,labels,jpeg='clusters.jpg'):

 # height and width

 h=getheight(clust)*20

 w=1200

 depth=getdepth(clust)

 # width is fixed, so scale distances accordingly

 scaling=float(w-150)/depth

 # Create a new image with a white background

 img=Image.new('RGB',(w,h),(255,255,255))

 draw=ImageDraw.Draw(img)

 draw.line((0,h/2,10,h/2),fill=(255,0,0))

 # Draw the first node

 drawnode(draw,clust,10,(h/2),scaling,labels)

 img.save(jpeg,'JPEG')


여기서 중요한 기능은 클러스터와 그 위치를 차지하는 드로이드다. 어린이 노드의 높이를 재고, 어디에 있어야 하는지를 계산하고, 그 노드에 하나의 긴 수직선과 두 개의 수평선인 선을 그린다. 수평선의 길이는 클러스터에 오류가 있는 정도에 따라 결정된다. 줄이 길면 클러스터를 생성하기 위해 병합된 두 클러스터가 그렇게 비슷하지 않은 반면, 줄이 짧으면 거의 동일하다는 것을 보여준다. 그리기 기능을 클러스터에 추가하십시오.피:



def drawnode(draw,clust,x,y,scaling,labels):

 if clust.id<0:

 h1=getheight(clust.left)*20

 h2=getheight(clust.right)*20

 top=y-(h1+h2)/2

 bottom=y+(h1+h2)/2

 # Line length

 ll=clust.distance*scaling

 # Vertical line from this cluster to children

 draw.line((x,top+h1/2,x,bottom-h2/2),fill=(255,0,0))

 # Horizontal line to left item

 draw.line((x,top+h1/2,x+ll,top+h1/2),fill=(255,0,0))

 # Horizontal line to right item

 draw.line((x,bottom-h2/2,x+ll,bottom-h2/2),fill=(255,0,0))

 # Call the function to draw the left and right nodes

 drawnode(draw,clust.left,x+ll,top+h1/2,scaling,labels)

 drawnode(draw,clust.right,x+ll,bottom-h2/2,scaling,labels)

 else:

 # If this is an endpoint, draw the item label

 draw.text((x+5,y-7),labels[clust.id],(0,0,0))


이것은 dendrogram과 함께 blogclust.jpg라는 파일을 생성하게 될 것이다. 덴드로그램은 그림 3-3에 표시된 것과 유사하게 보여야 한다. 원하는 경우 높이 및 너비 설정을 변경하여 인쇄하기 쉽거나 덜 어수선하도록 할 수 있다.

  • 네이버 블로그 공유하기
  • 네이버 밴드에 공유하기
  • 트위터 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기