본문 바로가기

Deep Learning Tools/Nengo

Nengo 음성 데이터를 neural network에 입력으로 넣기

음성 데이터를 이용해 neuron의 활성을 조절해보자!


먼저 librosa를 이용해 음성파일을 load해보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import librosa
import librosa.display
import IPython.display
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.font_manager as fm
 
import tensorflow as tf
 
%matplotlib inline
 
audio_path = '4_3273.wav'
 
y, sr = librosa.load(audio_path)
 
plt.figure()
plt.plot(y)
cs






1
2
3
4
5
6
time_duration = int(librosa.get_duration(y=y, sr=sr) * 1000)
data_length = y.shape[0]
print("time duration: " + str(time_duration) + " ms")
print("sampling rate: " + str(sr))
print("data length: " + str(data_length))
 
cs



time duration: 3529 ms
sampling rate: 22050
data length: 77824


3.5초짜리 데이터이며, sampling rate가 22050으로 총 77824개의 데이터가 저장되었다.

즉, 1초의 음성이 22050개의 데이터로 분리되어 저장되어 있다.

1개의 데이터가 0.0000453초의 음성을 표현한다는 것이다. (0.0000453 * 22050 = 1)


Nengo simulator의 경우, dt가 0.001초로 simulation이 실행된다.

즉, 0.0000453초의 데이터로는 Nengo에서 simulation을 수행할 수 없다.


음성데이터를 입력으로 받는지 테스트를 해보려고 하는 거니까,

간단한 input 함수를 구현해보았다.


1
2
3
4
def voice_input(t):
    ms = t * 1000
    voice = y[int((data_length / time_duration) * int(ms))]
    return voice
cs


t는 Nengo simulation이 수행될 때마다 호출하며, second 단위의 시간이 입력된다.

즉, 0.001, 0.002, 0.003 이렇게..


이 input을 받는 network를 설계해보자


1
2
3
4
5
6
7
8
9
with model:
    voice = nengo.Node(voice_input)
    A = nengo.Ensemble(80, dimensions=1)
    nengo.Connection(voice, A, synapse=0.01)
    
    p = nengo.Probe(A, synapse=0.01)
    inp_p = nengo.Probe(voice)
    spike_p = nengo.Probe(A.neurons)
    voltage_p = nengo.Probe(A.neurons, 'voltage')
cs


매우 간단한 1차원의 input->A neuron 집단으로 구성된 network다.

Neuron은 대충 80개로 구성해보았다.


80개 neuron의 발화 형태를 살펴볼까?


1
2
3
4
5
6
7
with nengo.Simulator(model) as sim: # this is the only line that changes
    plt.figure()
    plt.plot(*nengo.utils.ensemble.tuning_curves(A, sim))
    plt.xlabel("input value")
    plt.ylabel("firing rate")
    plt.title(str(nengo.LIF()))
    sim.run(3)
cs



이쁘게 잘 발화한다.



1
2
with nengo.Simulator(model) as sim:
    sim.run(int(time_duration-1/ 1000)
cs



Run을 하고 살펴보면..


1
2
3
4
5
6
7
8
9
10
11
12
from nengo.utils.matplotlib import rasterplot
 
plt.figure()
plt.plot(sim.trange(), sim.data[inp_p], 'r', label="Input")
plt.plot(sim.trange(), sim.data[p], label="A output")
plt.xlim(05)
plt.legend()
 
plt.figure()
rasterplot(sim.trange(), sim.data[spike_p])
plt.xlim(05);
 
cs



Fail!!!! ^^;;


Wav의 정보를 direct로 받는건 무리가 좀 있는 것 같다..



일부만 확대해서 봐도 input wave의 활성을 따라가지 못하는게 보인다.


그럼 mel spectrogram을 이용해볼까?



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
nMels = 80
= librosa.feature.melspectrogram(y, sr=sr, n_mels=nMels) 
 
log_S = librosa.logamplitude(S, ref_power=np.max)
plt.figure(figsize=(124))
librosa.display.specshow(log_S, sr=sr, x_axis='time', y_axis='mel')
plt.title('mel power spectrogram')
plt.colorbar(format='%+02.0f dB')
plt.tight_layout()
plt.show()
 
def half_normalize(S):
    return (S - S.min()/2/ (-S.min()/2)
 
def simple_normalize(S):
    return (S - S.min()) / (-S.min())
 
norm_S = half_normalize(log_S)
#norm_S = simple_normalize(log_S)
 
plt.figure(figsize=(124))
librosa.display.specshow(norm_S, sr=sr, x_axis='time', y_axis='mel')
plt.title('norm mel power spectrogram')
plt.colorbar(format='%+0.2f dB')
plt.tight_layout()
plt.show()
cs



일부러 mel spectrogram값을 -1에서 1로 변환시켜보았다.


역시 앞선 input 함수와 마찬가지로, mel spectrogram을 출력하는 input 함수를 만들었다.


1
2
3
4
5
6
7
8
9
10
transposed_norm_S = norm_S.transpose()
frame_size = int(time_duration/transposed_norm_S.shape[0])+1
 
print(transposed_norm_S.shape)
 
def voice_input(t):
    ms = int(t * 1000)
    frame_num = int(ms / frame_size)
    voice = transposed_norm_S[frame_num]
    return voice
cs


똑같이 network를 만드는데, 이번엔 80개의 neuron이 서로 다른 입력을 받을 수 있게 하기 위해 dimension을 80으로 구성해보았다.

1차원으로 구현해도 neuron마다 다른 입력을 받게 할수도 있는데 대충 아는 범위 내에서..


1
2
3
4
5
6
7
8
9
10
11
neuron_number = 80
with nengo.Network() as net:
    voice = nengo.Node(output=voice_input)
    neuronsEns = nengo.Ensemble(neuron_number, dimensions=neuron_number, max_rates=([100* neuron_number))
    
    nengo.Connection(voice, neuronsEns, synapse=0.01)
    
    voice_probe = nengo.Probe(voice)
    neurons_probe = nengo.Probe(neuronsEns, synapse=0.01)
    spike_probe = nengo.Probe(neuronsEns.neurons)
    voltage_probe = nengo.Probe(neuronsEns.neurons, 'voltage')
cs



1
2
with nengo.Simulator(net) as sim:
    sim.run(int(time_duration) / 1000)
cs


결과를 출력해보자


1
2
3
4
5
6
7
plt.figure(figsize=(204))
plt.subplot(121)
librosa.display.specshow(norm_S, sr=sr, x_axis='time', y_axis='mel')
 
plt.subplot(122)
rasterplot(sim.trange(), sim.data[spike_probe])
plt.xlabel('time [s]');
cs



대~~충 spectrogram을 입력으로 받는 network가 구성된 것 같다 ^^;;


좀 더 Nengo 문서를 자세히 봐야겠다..