File size: 3,534 Bytes
8106e91
 
 
 
 
 
 
 
 
7d392e4
8106e91
 
 
 
 
 
 
 
 
92d41b6
8106e91
 
 
92d41b6
8106e91
 
 
 
 
 
 
 
 
 
 
 
 
 
6e96d54
 
 
8106e91
 
 
 
 
 
 
 
6e96d54
 
7d392e4
6e96d54
 
 
 
7d392e4
6e96d54
 
8106e91
5e36e77
27a3ddf
 
8106e91
27a3ddf
 
 
8106e91
 
27a3ddf
8106e91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92d41b6
 
8106e91
 
 
 
 
 
 
 
 
 
 
 
 
 
27a3ddf
 
8106e91
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
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
57
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
109
110
111
112
113
114
115
116
import pandas as pd
import streamlit as st

from src.config import APP_PAGE_HEADER
from src.utils import search_df

APP_PAGE_HEADER()


@st.cache(allow_output_mutation=True)
class LoadData:
    train: pd.DataFrame = pd.read_csv("data/train.csv")
    train = train.sample(frac=1).reset_index(drop=True)  # shuffle data

    test: pd.DataFrame = pd.read_csv("data/test.csv")
    titles: pd.DataFrame = pd.read_csv("data/titles.csv")

    # add code titles to train data
    merged = train.merge(titles, left_on="context", right_on="code")
    train_df = merged[['id', 'anchor', 'context', 'target', 'title', 'score']].copy()

    # add relations / edges for knowledge graph
    train_kg: pd.DataFrame = train_df.copy()
    train_kg['relation'] = train_kg['context'] + " || " + train_kg['title'] + " || " + train_kg['score'].astype(str)


class App:
    def __init__(self):
        self.data = LoadData()

    def run(self, debug=False):
        self.render_header(debug)
        self.render_body(debug)
        self.render_footer(debug)

    def render_header(self, *args, **kwargs):
        pass

    @staticmethod
    def render_body(*args, **kwargs):
        Helper().display_train_data()

        Helper().visualize()

    def render_footer(self, *args, **kwargs):
        pass


class Helper(App):

    def display_train_data(self):
        data = self.data.train_df

        st.write(f"> Train data `{data.shape[0]}` rows")
        filter_ = st.text_input("search phrases", "")
        if filter_:
            data = search_df(data, filter_)
        st.write(data)

    def visualize(self, *args, **kwargs):
        st.subheader("Visualize Phrases as a Network Graph")
        data = self.data.train_kg

        # filter data for visualization
        # -- sampling
        MAX_EDGES = 200
        sample = data[:MAX_EDGES]

        st1, st2 = st.columns(2)
        score = st1.selectbox("visualize phrases by similarity score", [""] + data["score"].unique().tolist())
        if score:
            sample = data[data["score"] == float(score)][:MAX_EDGES]

        filter_ = st2.text_input("search term to visualize matching phrases")
        if filter_:
            sample = search_df(data, filter_)[:MAX_EDGES]

        # create graph
        nodes = list(sample["anchor"].unique()) + list(sample["target"].unique())
        edges = [(h, t) for h, t in zip(sample["anchor"].tolist(), sample["target"].tolist())]
        labels = sample["relation"].tolist()
        edge_labels = dict(zip(edges, labels))

        # create PyVis network from the graph data
        self.pyvis_network(nodes, edge_labels)
        st.write(f"> the visualized sample size: {sample.shape[0]}")
        st.write(sample)

    def pyvis_network(self, nodes, edge_labels):

        from stvis import pv_static

        g = self.build_network(edge_labels, nodes)

        pv_static(g)

    @staticmethod
    @st.experimental_singleton
    def build_network(edge_labels, nodes):
        # src: https://stackoverflow.com/a/67279471/2839786
        from pyvis.network import Network
        g = Network(height="800px", width="1400px", heading="U.S. Patent Phrase/Context Network",
                    bgcolor="#bbbffz")  # notebook=True,
        for node in nodes:
            g.add_node(node)
        for e in edge_labels:
            n1, n2 = e[0], e[1]
            label = edge_labels[e]
            g.add_edge(n1, n2, title=label, show_edge_weights=True)  # weight 42
        return g


if __name__ == "__main__":
    app = App()
    app.run(debug=True)