Skip to content

flgo.benchmark.toolkits.visualization

community_layout(g, partition)

Compute the layout for a modular graph.


g -- networkx.Graph or networkx.DiGraph instance graph to plot

partition -- dict mapping int node -> int community graph partitions


pos -- dict mapping int node -> (float x, float y) node positions

Source code in flgo\benchmark\toolkits\visualization.py
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
def community_layout(g, partition):
    """
    Compute the layout for a modular graph.


    Arguments:
    ----------
    g -- networkx.Graph or networkx.DiGraph instance
        graph to plot

    partition -- dict mapping int node -> int community
        graph partitions


    Returns:
    --------
    pos -- dict mapping int node -> (float x, float y)
        node positions

    """

    pos_communities = _position_communities(g, partition, scale=3.)

    pos_nodes = _position_nodes(g, partition, scale=1.)

    # combine positions
    pos = dict()
    for node in g.nodes():
        pos[node] = pos_communities[node] + pos_nodes[node]

    return pos

visualize_by_class(generator, partitioner, task_path)

Visualize the partitioned classification dataset and save the figure

Parameters:

Name Type Description Default
generator flgo.benchmark.toolkits.BasicTaskGenerator

task generator

required
partitioner flgo.benchmark.toolkits.partition.BasicPartitioner

partitioner

required
task_path str

the path storing the figure

required
Source code in flgo\benchmark\toolkits\visualization.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def visualize_by_class(generator, partitioner, task_path:str):
    r"""
    Visualize the partitioned classification dataset and save the figure

    Args:
        generator (flgo.benchmark.toolkits.BasicTaskGenerator): task generator
        partitioner (flgo.benchmark.toolkits.partition.BasicPartitioner): partitioner
        task_path (str): the path storing the figure
    """
    all_labels = [d[-1] for d in generator.train_data]
    num_classes = len(set(all_labels))
    ax = plt.subplots()
    colors = [key for key in matplotlib.colors.CSS4_COLORS.keys()]
    random.shuffle(colors)
    client_height = 1
    if hasattr(generator.partitioner, 'num_parties'):
        n = generator.partitioner.num_parties
    else:
        n = generator.partitioner.num_clients
    if hasattr(partitioner, 'dirichlet_dist'):
        client_dist = generator.partitioner.dirichlet_dist.tolist()
        data_columns = [sum(cprop) for cprop in client_dist]
        row_map = {k: i for k, i in zip(np.argsort(data_columns), [_ for _ in range(n)])}
        for cid, cprop in enumerate(client_dist):
            offset = 0
            y_bottom = row_map[cid] - client_height / 2.0
            y_top = row_map[cid] + client_height / 2.0
            for lbi in range(len(cprop)):
                plt.fill_between([offset, offset + cprop[lbi]], y_bottom, y_top, facecolor=colors[lbi])
                # plt.barh(cid, cprop[lbi], client_height, left=offset, color=)
                offset += cprop[lbi]
    else:
        data_columns = [len(cidx) for cidx in generator.local_datas]
        row_map = {k: i for k, i in zip(np.argsort(data_columns), [_ for _ in range(n)])}
        for cid, cidxs in enumerate(generator.local_datas):
            labels = [int(generator.train_data[did][-1]) for did in cidxs]
            lb_counter = collections.Counter(labels)
            offset = 0
            y_bottom = row_map[cid] - client_height / 2.0
            y_top = row_map[cid] + client_height / 2.0
            for lbi in range(num_classes):
                plt.fill_between([offset, offset + lb_counter[lbi]], y_bottom, y_top, facecolor=colors[lbi%len(colors)])
                offset += lb_counter[lbi]
    plt.xlim(0, max(data_columns))
    plt.ylim(-0.5, n- 0.5)
    plt.ylabel('Client ID')
    plt.xlabel('Number of Samples')
    plt.savefig(os.path.join(task_path, 'res.png'))
    plt.show()

visualize_by_community(generator, partitioner, task_path)

Visualize the partitioned graph node-level dataset and save the figure

Parameters:

Name Type Description Default
generator flgo.benchmark.toolkits.BasicTaskGenerator

task generator

required
partitioner flgo.benchmark.toolkits.partition.BasicPartitioner

partitioner

required
task_path str

the path storing the figure

required
Source code in flgo\benchmark\toolkits\visualization.py
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def visualize_by_community(generator, partitioner, task_path:str):
    r"""
    Visualize the partitioned graph node-level dataset and save the figure

    Args:
        generator (flgo.benchmark.toolkits.BasicTaskGenerator): task generator
        partitioner (flgo.benchmark.toolkits.partition.BasicPartitioner): partitioner
        task_path (str): the path storing the figure
    """
    # from communities.
    import networkx as nx
    import community
    community = community.community_louvain.best_partition(generator.train_data)
    groups = collections.defaultdict(list)
    for ni, gi in community.items():
        groups[gi].append(ni)
    groups = list(groups.values())

    local_datas = generator.local_datas
    client_community = {}
    for cid, nodes in enumerate(local_datas):
        for node in nodes: client_community[node] = cid
    G = generator.train_data
    total_edges = len(G.edges)
    subgraphs = [nx.subgraph(G, li) for li in local_datas]
    local_edges = [len(g.edges) for g in subgraphs]
    edge_losing_rate = 1.0*(total_edges-sum(local_edges))/total_edges
    std_edge_num = np.std(local_edges)
    Gdegree = sum([G.degree[i] for i in G.nodes])/len(G.nodes)
    subgraphs_degree = [sum([g.degree[i] for i in g.nodes])/len(g.nodes) for g in subgraphs]
    std_degree = np.std(subgraphs_degree)
    mean_degree = np.mean(subgraphs_degree)
    title = "num_clients:{}\nglobal_edges:{} | edge_losing_rate:{:.4f} | std_edge_num:{:.4f}\nglobal_degree:{:.4f} | ave_degree:{:.4f} | std_degree:{:.4f}".format(len(local_datas), total_edges, edge_losing_rate, std_edge_num, Gdegree, mean_degree, std_degree)
    colors = [key for key in matplotlib.colors.XKCD_COLORS.keys()]
    pos = community_layout(G, client_community)
    nx.draw_networkx_edges(G, pos, edgelist=list(G.edges), width=0.5, alpha=0.5)
    local_colors = ['r', 'b', 'g']
    for cid, cnodes in enumerate(local_datas):
        nx.draw_networkx_nodes(G, pos, cnodes, node_size=800,alpha=0.02,
                               node_color=local_colors[cid%len(local_colors)],
                               node_shape='o')

    for cid, cnodes in enumerate(groups):
        nx.draw_networkx_nodes(G, pos, cnodes, node_size=20,
                               node_color=colors[cid%len(colors)],
                               node_shape='>')

    plt.title(title)
    plt.savefig(os.path.join(task_path, 'res.png'))
    plt.show()
    return