def split(self, node):
# Perform normalized cut
try:
ind = SpectralClustering(2, affinity = 'precomputed', assign_labels = 'discretize').fit_predict(node['affinity'])
except KeyboardInterrupt:
raise
except:
return None, None, 0
# Create left and right node
mask1, mask2 = (ind == 0), (ind == 1)
if not (np.any(mask1) and np.any(mask2)):
return None, None, 0
left = { 'depth' : node['depth'] + 1, 'height' : 0, 'size' : 0, 'leafs' : 1, 'children' : [], 'parent' : node, 'items' : [f for i, f in enumerate(node['items']) if ind[i] == 0], 'affinity' : node['affinity'][np.ix_(mask1, mask1)] }
right = { 'depth' : node['depth'] + 1, 'height' : 0, 'size' : 0, 'leafs' : 1, 'children' : [], 'parent' : node, 'items' : [f for i, f in enumerate(node['items']) if ind[i] == 1], 'affinity' : node['affinity'][np.ix_(mask2, mask2)] }
# Force the node with the lower minimum distance to the query to be the left node
if ind[0] == 1: # items are already sorted when passed to fit(), so we just need to look at the first item instead of re-computing all distances
left, right = right, left
# Modify parent
node['children'] = [left, right]
# Modify parent chain
parent = node
while parent is not None:
parent['height'] += 1
parent['size'] += 2
parent['leafs'] += 1
parent = parent['parent']
return left, right, self.ncut_value(node['affinity'], ind)
评论列表
文章目录