0

I'm trying to visualize Kullback-Leibler divergence (how much one prob. dist. differs from another) by plotting two normal probability distribution graphs on top each other. I want to change mean and std. value of each graph using sliders, but I wasn't able to make the sliders actually change anything so far. Could you take a look and help me figure out how to make it work? Here's where I am at:

      import numpy as np
        from scipy.stats import norm
        from matplotlib import pyplot as plt
        import tensorflow as tf
        import seaborn as sns
        sns.set()
        
        from matplotlib.widgets import Slider
        import matplotlib.pyplot as plt
        
        def kl_divergence(p, q):
            return np.sum(np.where(p != 0, p * np.log(p / q), 0))
        
        mean_1_init = 0
        std_1_init = 2
        mean_2_init = 2
        std_2_init = 2
        
        x = np.arange(-10, 10, 0.001)
        p = norm.pdf(x, mean_1_init, std_1_init)
        q = norm.pdf(x, mean_2_init, std_2_init)
        
        plt.title('KL(P||Q) = %1.3f' % kl_divergence(p, q))
        plt.plot(x, p)
        plt.plot(x, q, c='red')
        
        ax_slider_mean_1_init = plt.axes([0.125, 0.03, 0.775, 0.03])
        ax_slider_std_1_init = plt.axes([0.125, 0.07, 0.775, 0.03])
        
        a_slider = Slider(ax_slider_mean_1_init, r"$mean 1$", 0, 100, valinit=mean_1_init)
        k_slider = Slider(ax_slider_std_1_init, r"$std dev 1$", 0, 100, valinit=std_1_init, valstep=1)
        
        def update():
            mean_1_init, std_1_init = a_slider.val, k_slider.val
            p = norm.pdf(x, mean_1_init, std_1_init)
            q = norm.pdf(x, mean_2_init, std_2_init)
        
        a_slider.on_changed(update)
        k_slider.on_changed(update)
        
        update()
        plt.show()

When I run it, the graphs open with the sliders. But when I change the values on sliders, the graphs don't change and the following error message appears:

 Traceback (most recent call last):
  File "C:\Users\...\miniconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 224, in process
    func(*args, **kwargs)
  File "C:\Users\...\miniconda3\lib\site-packages\matplotlib\widgets.py", line 440, in _update
    self.set_val(val)
  File "C:\Users\...\miniconda3\lib\site-packages\matplotlib\widgets.py", line 474, in set_val
    func(val)
TypeError: update() takes 0 positional arguments but 1 was given
  • Please include the full error traceback. – mkrieger1 Oct 02 '22 at 23:22
  • I added the full traceback. Thanks. –  Oct 02 '22 at 23:29
  • Ah, you passed `update` as callback to `slider.on_changed`. As the error message says, it tries to pass 1 argument to `update` but it accepts only 0 arguments. You need to change `update` so that it accepts 1 argument. – mkrieger1 Oct 02 '22 at 23:35
  • Right, thanks! I changed 'update', but the sliders still don't change the plot. I can change the value on the sliders, but the plot's mean and std. dev. doesn't actually change at all. –  Oct 02 '22 at 23:41
  • For that to happen, `update` would have to change the plot. It doesn't do this at all. Currently it calculates two values and then discards them. – mkrieger1 Oct 02 '22 at 23:44
  • Right, how can I make it so that it changes the plot? –  Oct 02 '22 at 23:48
  • What came next after you calculated p and q earlier in the code? I would do the same again. – mkrieger1 Oct 02 '22 at 23:57
  • I added that in 'update', but it still doesn't change the initial plot. –  Oct 03 '22 at 00:09

0 Answers0