A dashboard to visualize DeGroot learning on networks with Python and Streamlit

Image for post
Image for post
Photo by Markus Winkler on Unsplash

DeGroot shows how opinions are formed and consensus arises when people or entities take in account others’ opinions to update their own. It also gives an intuition about the meaning of “eigenvector centrality” as a measure of influence. Sources: https://github.com/antigones/streamlit-degroot

In the DeGroot model, people have opinions and those opinions are represented with a vector of probabilities, p. Probabilities can represent some kind of belief about a subject, the likeliness of an event to occur, how much the agent likes something. Society is modeled with a stochastic matrix, representing connections and interaction between individuals: value Tij is the weight agent i gives to j’s opinion when it comes to update i’s own.

As an example, take the following matrix:

Image for post
Image for post

In this society, agent 1 weights own belief as 2 but does not care about agent 3; agent 2 weights own belief as much as 3 but does not care about 1; agent 3 only cares about agent 1.

Suppose p(0) to be as following:

Image for post
Image for post

We can think that this specific vector represents the fact that agent 1 fully believes that an event will occur, while agents 2 and 3 are totally skeptical about this event to take place.

At every step beliefs get updated in the following way:

Image for post
Image for post

Updating the vector is simulating people taking in account other peoples’ opinions and updating their own at any given time.

Applying some math and solving p(t) equality, it is possible to observe that:

Image for post
Image for post

and to realize that, on the long term, the result of the updating process is more about T^t than about p(0)

In fact, when the limit exists, beliefs converge and agents reach a consensus:

Image for post
Image for post
Image for post
Image for post

and in this setting, agent 1 and agent 2 have far more influence than agent 1:

Image for post
Image for post

Note also that

(2/5, 2/5, 1/5)

is also an eigenvector for T: DeGroot also gives a glimpse about the meaning of eigenvector centrality as a measure of social influence.

Developing a dashboard to visualize DeGroot convergence

To visualize how DeGroot evolves over time over a sample society, using Python turned out to be a fairly good choice (numpy is awesome to perform matrix math!).

We can define deGroot as a function of the society (environment) and initial beliefs vector (beliefs). Keeping track of consensus reaching and a variable “i” to stop the algorithm when it does not converge (1000 is a symbolic upper limit), we update the beliefs vector by multiplying T by p.

Check for convergence is done by inspecting the difference between previous beliefs vector and current one: if it is sufficiently small then we assume that the convergence has been reached and exit the loop.

import numpy as npdef deGroot(environment, beliefs):    i = 0
consensus = False
while (consensus == False and i < 1000):
old_beliefs = beliefs
beliefs = environment @ beliefs
if (np.all(old_beliefs — beliefs < np.full(len(beliefs),sys.float_info.epsilon))):
consensus = True
i = i + 1
return beliefs

To track the consensus reaching steps, we define a similar function:

def deGrootSteps(environment, beliefs):    steps = []
i = 0
consensus = False
while (consensus == False and i < 1000):
old_beliefs = beliefs
beliefs = environment @ beliefs
if (np.all(old_beliefs — beliefs < np.full(len(beliefs),sys.float_info.epsilon))):
consensus = True
i = i + 1
steps.append(beliefs) return steps

which basically fill an array of “steps” to consensus.

We also add an helper function to format decimal as fraction (we don’t want to visualize matrices with very long numbers) and a function to display matrix as Latex formula:

from fractions import Fraction as frac
import numpy as np
def convert_to_frac(mat):
result = []
mat_list = mat.astype(str).tolist()
for i in range(0, len(mat_list)):
result.append([])
for j in range(0, len(mat_list[i])):
result[i].append(
str(frac(str(mat_list[i][j])).limit_denominator(10)))
return result
def convert_to_latex(mat):
mat_list = convert_to_frac(mat)
mat_list_rows = list(map(r” & “.join, mat_list))
mat_latex_content = r” \\\ “.join(mat_list_rows)
return mat_latex_content

Streamlit is a quite nice package to easily create interactive web apps with python.

Just add it to the virtual environment by typing:

pip install streamlit

Streamlit provides nice components to interact with (slider, texts, latex formulae…).

We add a title and some descriptive text:

import streamlit as stst.title("DeGroot")st.write("DeGroot gives an insight about how network topology influence spread of information and opinion formation.It also gives an intuition about the reason why eigenvector centrality expresses influence.")st.write("Move the slide to inspect the belief vector as it updates according to DeGroot model.")

We also want to add a slider to control the simulation:

p0 = np.matrix([1, 0, 0]).T
T = np.matrix([[1/2, 1/2, 0], [0, 1/2, 1/2], [1, 0, 0]])
dg_steps = dg.deGrootSteps(T, p0)
step = st.slider('Step', 0, len(dg_steps)-1, 0)
st.write("Step: ", step, '')

We can also begin to inspect how the app will look like by launching our py script as a streamlit “app”:

streamlit run app.py

The browser will open the app page:

Image for post
Image for post

Note that the number of steps will update accordingly to slider value.

We can use networkx to draw network topology and Streamlit’s “graphviz_chart”:

G = nx.from_numpy_matrix(T, create_using=nx.MultiDiGraph())T_label = u.convert_to_frac(T)
for i, j, d in G.edges(data=True):
d[‘label’] = T_label[i][j]
dot = nx.nx_pydot.to_pydot(G)col1, col2 = st.beta_columns(2)
with col1:
st.graphviz_chart(dot.to_string())

As Streamlit can display Latex, we use st.latex to display society matrix and beliefs vector:

ltx_mat = u.convert_to_latex(T)
b_mat = u.convert_to_latex(dg_steps[step])
p0_mat = u.convert_to_latex(p0)
col3, col4, col5 = st.beta_columns(3)with col3:
st.latex(r'''
T =
\begin{pmatrix}
'''+ltx_mat+r'''
\end{pmatrix}
''')
with col4:
st.latex(r'''
p(0) =
\begin{pmatrix} ''' + p0_mat + r'''\end{pmatrix}
''')
with col5:
st.latex(r'''
T^{t}p(0) {\rightarrow}
\begin{pmatrix}
''' + b_mat + r'''
\end{pmatrix}
''')

We also display Ttconvergence in the same way (with some index adjustment to skip step 0):

st.title("Convergence of T")T_t = np.linalg.matrix_power(T, step+1)
T_t_mat = u.convert_to_latex(T_t)
st.latex(r'''
T^{t} {\rightarrow}
\begin{pmatrix}
''' + T_t_mat + r'''
\end{pmatrix}
''')

And here’s the final result:

Image for post
Image for post

References: “Social and economic networks”, Mattew O. Jackson, Princeton; Wikipedia, https://en.wikipedia.org/wiki/DeGroot_learning

Full-time Human-computer interpreter

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store