mirror of https://github.com/drowe67/phasenn.git
118 lines
3.3 KiB
Python
Executable File
118 lines
3.3 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# phasenn_test7.py
|
|
#
|
|
# David Rowe Oct 2019
|
|
|
|
# Keras model for testing phase modelling using NNs. Here we try
|
|
# estimating the phase of a 2nd order system from it's amplitudes.
|
|
# This models the dispersive component of speech phase spectra, up
|
|
# until now we have been testing with the linear phase component.
|
|
# This script emulates a Hilbert Transform, note however in practice
|
|
# speech is not minimum phase so HTs have there limitations for real
|
|
# speech signals.
|
|
|
|
import numpy as np
|
|
from scipy import signal
|
|
import sys
|
|
from keras.layers import Dense
|
|
from keras import models,layers
|
|
from keras import initializers
|
|
import keras.backend as K
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
# constants
|
|
|
|
N = 80 # number of time domain samples in frame
|
|
nb_samples = 10000
|
|
nb_batch = 64
|
|
nb_epochs = 10
|
|
width = 256
|
|
pairs = 2*width
|
|
fo_min = 50
|
|
fo_max = 400
|
|
Fs = 8000
|
|
|
|
# Generate training data. Sparse log magnitude spectrum is input,
|
|
# phase spectrum of 2nd order system the output/target
|
|
|
|
mag = np.zeros((nb_samples, width))
|
|
phase = np.zeros((nb_samples, pairs))
|
|
|
|
for i in range(nb_samples):
|
|
|
|
# choose a random fo
|
|
r = np.random.rand(1)
|
|
fo = fo_min + (fo_max-fo_min)*r[0]
|
|
Wo = fo*2*np.pi/Fs
|
|
L = int(np.floor(np.pi/Wo))
|
|
|
|
# sample 2nd order IIR filter with random peak freq and amplitude
|
|
|
|
r = np.random.rand(2)
|
|
alpha = 0.1*np.pi + 0.8*np.pi*r[0]
|
|
gamma = r[1]
|
|
w,h = signal.freqz(1, [1, -2*gamma*np.cos(alpha), gamma*gamma], range(1,L)*Wo)
|
|
|
|
# map to sparse input and output arrays
|
|
|
|
for m in range(1,L):
|
|
bin = int(np.floor(m*Wo*width/np.pi))
|
|
mag[i,bin] = np.log10(np.abs(h[m-1]))
|
|
phase_rect = h[m-1]/np.abs(h[m-1])
|
|
phase[i,2*bin] = phase_rect.real
|
|
phase[i,2*bin+1] = phase_rect.imag
|
|
|
|
print(mag.shape)
|
|
print(phase.shape)
|
|
|
|
model = models.Sequential()
|
|
model.add(layers.Dense(pairs, activation='relu', input_dim=width))
|
|
model.add(layers.Dense(pairs, input_dim=pairs))
|
|
model.summary()
|
|
|
|
# Compile and fit our model
|
|
|
|
from keras import optimizers
|
|
sgd = optimizers.SGD(lr=0.04, decay=1e-6, momentum=0.9, nesterov=True)
|
|
model.compile(loss='mse', optimizer=sgd)
|
|
history = model.fit(mag, phase, batch_size=nb_batch, epochs=nb_epochs)
|
|
|
|
# measure error in rectangular coordinates over all samples
|
|
|
|
phase_est = model.predict(mag)
|
|
err = (phase_est - phase)
|
|
var = np.var(err)
|
|
std = np.std(err)
|
|
print("rect var: %f std: %f" % (var,std))
|
|
|
|
err_angle = np.arctan2(err[:,1], 1)
|
|
print(err_angle.shape)
|
|
var = np.var(err_angle)
|
|
std = np.std(err_angle)
|
|
print("angle var: %4.2f std: %4.2f rads" % (var,std))
|
|
print("angle var: %4.2f std: %4.2f degs" % (var*180/np.pi,std*180/np.pi))
|
|
|
|
plot_en = 1;
|
|
if plot_en:
|
|
plt.figure(1)
|
|
plt.plot(history.history['loss'])
|
|
plt.title('model loss')
|
|
plt.xlabel('epoch')
|
|
|
|
plt.figure(2)
|
|
plt.hist(err_angle*180/np.pi, bins=20)
|
|
plt.title('phase angle error (deg)')
|
|
|
|
fig = plt.figure(3)
|
|
ax1 = fig.add_subplot(111)
|
|
plt.plot(20*mag[1,:])
|
|
ax2 = ax1.twinx()
|
|
phase = np.unwrap(np.arctan2(phase[1::2], phase[::2]))
|
|
plt.plot(phase, 'g')
|
|
phase_est = np.unwrap(np.arctan2(phase_est[1::2], phase_est[::2]))
|
|
plt.plot(phase, 'r')
|
|
|
|
plt.show()
|
|
|