4
$\begingroup$

I'm wondering if adding Gaussian Noise to two waveforms tends to decrease their Pearson correlation. Below is a simulation of adding noise to two waveforms (blue = np.sin(x) and orange = 1 + np.sin(1.1 * x)). While the means don't change very much, the Pearson correlation is much more affected. It makes sense the noise shouldn't change the mean since the noise itself has mean zero, however, for Pearson correlations, it's not obvious whether it'll tend to move the value up, down, or stay the same

noise_simulation

Mathematically I think this translates to this for the mean which does show it'll tend to stay the same

noise_mean

For Pearson correlations, this is what I get

noise_pearson

The numerator seems to grow as ε, while the denominator grows as sqrt(ε). So for small ε, the Pearson correlation will tend to zero since the denominator is larger. I'm not from a statistics background so any help would be greatly appreciated, thank you!

Code

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from tqdm.notebook import tqdm
from matplotlib import animation
from scipy.stats import pearsonr, spearmanr

sns.set()

def rand(y, noise=0.1):
    return y + noise * np.random.normal(size=y.shape)
    
def init():
    for line in lines:
        line.set_data([], [])
    act_text.set_text('')
    corr_text.set_text('')
    return tuple(lines) + (act_text, corr_text,)

def animate(i):
    global y1, y2
    y1 = rand(y1, noise=0.04)
    y2 = rand(y2, noise=0.04)
    lines[0].set_data(x, y1)
    lines[1].set_data(x, y2)
    
    y1s.append(y1.mean())
    y2s.append(y2.mean())
    pears.append(pearsonr(y1, y2)[0])
    act = "blue     = %.03f\norange = %.03f" % (y1s[-1], y2s[-1])
    corr = "\n%.04f" % pears[-1]
    act_text.set_text(act)
    corr_text.set_text(corr)
    return tuple(lines) + (act_text, corr_text)

end = 20
N = 200

x = np.linspace(0, end, N)
y1 = np.sin(x)
y2 = 1 + np.sin(1.1 * x)

fig = plt.figure(figsize=(14, 8))
ax = plt.axes(xlim=(-1, 21), ylim=(-2, 3.8))

lines = [plt.plot([], [])[0], plt.plot([], [])[0]]
params = {"fontsize": 24, "transform": ax.transAxes, "horizontalalignment": "center", "verticalalignment": "top"}
ax.text(0.15, 0.97, "\u0332".join("Mean"), **params)
ax.text(0.40, 0.97, "\u0332".join("Pearson"), **params)
params["horizontalalignment"] = "left"
act_text = ax.text(0.05, 0.90, "", **params)
corr_text = ax.text(0.35, 0.94, "", **params)
ax.tick_params(axis='both', which='major', labelsize=18)
ax.tick_params(axis='both', which='minor', labelsize=16)

pears, y1s, y2s = [], [], []

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=tqdm(range(100)), interval=20, blit=True)

anim.save("noise_simulation.mp4", fps=30, extra_args=['-vcodec', 'libx264']);
$\endgroup$

1 Answer 1

4
$\begingroup$

Pearson correlation is, a bit loosely speaking (but not that loosely), measuring how well the points fit a diagonal line. When the points are far from the line, as the noisy setting will show, they don’t fit the line so well, and the magnitude is near zero.

You are doing something a bit different by using sinusoidal waves, but the same idea applies: when the signal is noise, there is a poor fit to the sinusoid.

You can make this rigorous by going through the equations and taking limits. In your simulation, let the noise get very large, and watch the noise wash out the signal (even visually)

$\endgroup$
2
  • $\begingroup$ This helps! The noise is completely uncorrelated with each other so as it becomes dominant, it should definitely move the correlation towards zero $\endgroup$ Commented Jun 1, 2021 at 17:50
  • 1
    $\begingroup$ Precisely! The noise obscures the pattern, completely dominating in the limit. $\endgroup$
    – Dave
    Commented Jun 1, 2021 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.