Python 在重新初始化数据集后,丢失会返回到起始值

Python 在重新初始化数据集后,丢失会返回到起始值,python,tensorflow,tensorflow-datasets,Python,Tensorflow,Tensorflow Datasets,我正在用Python Tensorflow培训一个关于音频数据的LSTM网络。我的数据集是一组wave文件,read\u wavfiles将其转换为numpy数组的生成器。我决定尝试使用相同的数据集对我的网络进行20次训练,并编写了如下代码 from with_hyperparams import stft from model import lstm_network import tensorflow as tf def read_wavfile(): for file in it

我正在用Python Tensorflow培训一个关于音频数据的LSTM网络。我的数据集是一组wave文件,
read\u wavfiles
将其转换为
numpy
数组的生成器。我决定尝试使用相同的数据集对我的网络进行20次训练,并编写了如下代码

from with_hyperparams import stft
from model import lstm_network
import tensorflow as tf


def read_wavfile():
    for file in itertools.chain(DATA_PATH.glob("**/*.ogg"),
                                DATA_PATH.glob("**/*.wav")):
        waveform, samplerate = librosa.load(file, sr=hparams.sample_rate)
        if len(waveform.shape) > 1:
            waveform = waveform[:, 1]

        yield waveform    

audio_dataset = Dataset.from_generator(
    read_wavfile,
    tf.float32,
    tf.TensorShape([None]))

dataset = audio_dataset.padded_batch(5, padded_shapes=[None])

iterator = tf.data.Iterator.from_structure(dataset.output_types,
                                           dataset.output_shapes)
dataset_init_op = iterator.make_initializer(dataset)

signals = iterator.get_next()

magnitude_spectrograms = tf.abs(stft(signals))

output, loss = lstm_network(magnitude_spectrograms)

train_op = tf.train.AdamOptimizer(1e-3).minimize(loss)

init_op = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init_op)
    for i in range(20):
        print(i)
        sess.run(dataset_init_op)

        while True:
            try:
                l, _ = sess.run((loss, train_op))
                print(l)
            except tf.errors.OutOfRangeError:
                break
完整的代码,包括使用的足够自由的数据(带有IPA转录本的Wikipedia声音文件)

非免费数据(EMU语料库声音文件)确实有很大的不同,但我不知道如何向您展示:

  • 在整个数据集上运行脚本时,输出从迭代0开始,损失约5000,然后在数据集上减少到约1000。然后是一行
    1
    表示第二个循环,突然损失又达到了5000左右
  • 当将订单交换到
    DATA\u PATH.glob(“***/*.wav”)、DATA\u PATH.glob(“***/*.ogg”)
    时,损失从5000以下开始,下降到1000左右,然后再跳到4000左右,用于
    *.ogg
    样本
对样本进行重新排序会得到不同的结果,因此看起来WAV文件比OGG文件更相似。我有一个想法,洗牌在理想情况下应该发生在数据集级别,而不是依赖于以随机顺序读取数据。然而,这意味着将大量wav文件读入内存,这听起来不是一个好的解决方案

我的代码应该是什么样子?

请尝试以下操作:

  • 向输入管道添加
    dataset.shuffle(buffer\u size=1000)
  • 隔离调用
    loss
    ,以便在每次训练后进行评估
如下图所示:

更新输入管道 会议的最新情况
如果我能够访问一些数据样本,我可能能够更准确地提供帮助。现在,我在这里瞎工作,无论如何,一定要让我知道这是否有效。

这看起来像是架构中的一个问题。首先,您在移动中生成数据,尽管这是一种常用的技术,但并不总是最合理的选择。这是因为:

Dataset.from_generator()
的一个缺点是对结果数据集进行洗牌 对于大小为n的洗牌缓冲区,需要加载n个示例。这 将在管道中创建周期性暂停(大n)或 导致潜在的不良洗牌(小n)

最好将数据转换为numpy阵列,然后将numpy阵列存储在磁盘上,用作数据集,如下所示:

def array_to_tfrecords(X, y, output_file):
  feature = {
    'X': tf.train.Feature(float_list=tf.train.FloatList(value=X.flatten())),
    'y': tf.train.Feature(float_list=tf.train.FloatList(value=y.flatten()))
  }
  example = tf.train.Example(features=tf.train.Features(feature=feature))
  serialized = example.SerializeToString()

  writer = tf.python_io.TFRecordWriter(output_file)
  writer.write(serialized)
  writer.close()
这将使来自\u生成器的
数据集组件不再出现问题。然后可以使用以下方法读取数据:

def read_tfrecords(file_names=("file1.tfrecord", "file2.tfrecord", "file3.tfrecord"),
                   buffer_size=10000,
                   batch_size=100):
  dataset = tf.contrib.data.TFRecordDataset(file_names)
  dataset = dataset.map(parse_proto)
  dataset = dataset.shuffle(buffer_size)
  dataset = dataset.repeat()
  dataset = dataset.batch(batch_size)
  return tf.contrib.data.Iterator.from_structure(dataset.output_types, dataset.output_shapes)
这将确保您的数据被彻底洗牌,并提供更好的结果

此外,我相信您将从一些数据预处理中获益。首先,尝试将数据集中的所有文件转换为标准波形,然后将该数据保存到TFR记录中。目前,您正在将它们转换为WAVE,并使用librosa标准化采样率,但这并没有标准化通道。相反,请尝试使用以下函数:

from pydub import AudioSegment
def convert(path):

    #open file (supports all ffmpeg supported filetypes) 
    audio = AudioSegment.from_file(path, path.split('.')[-1].lower())

    #set to mono
    audio = audio.set_channels(1)

    #set to 44.1 KHz
    audio = audio.set_frame_rate(44100)

    #save as wav
    audio.export(path, format="wav")
最后,您可能会发现以浮点形式读取声音文件并不符合您的最佳利益。你应该考虑一些类似的事情:

import scipy.io.wavfile as wave
import python_speech_features as psf
def getSpectrogram(path, winlen=0.025, winstep=0.01, NFFT=512):

    #open wav file
    (rate,sig) = wave.read(path)

    #get frames
    winfunc=lambda x:np.ones((x,))
    frames = psf.sigproc.framesig(sig, winlen*rate, winstep*rate, winfunc)

    #Magnitude Spectrogram
    magspec = np.rot90(psf.sigproc.magspec(frames, NFFT))

    #noise reduction (mean substract)
    magspec -= magspec.mean(axis=0)

    #normalize values between 0 and 1
    magspec -= magspec.min(axis=0)
    magspec /= magspec.max(axis=0)

    #show spec dimensions
    print magspec.shape    

    return magspec
然后应用如下函数:

#convert file if you need to
convert(filepath)

#get spectrogram
spec = getSpectrogram(filepath)

这将把WAVE文件中的数据解析成图像,然后您可以用处理任何图像分类问题的相同方式来处理这些图像

我真的不知道编程的约定
tensorflow
。请随意编辑我的代码片段,使其符合任何此类约定,从而便于其他用户阅读。对于初学者,全局变量初始化通常在
tf.Session
的范围内完成。将tf.Session()作为sess:
循环帮助在
中移动
init\u op=tf.global\u variables\u initializer()
?没有任何数据就很难进行调试。对于调试,有和。我自己才刚刚开始学习TensorBoard,但它似乎有很大的帮助潜力。听起来你的数据集有问题。你能为你的
read\u wavfile
功能添加代码/粗略描述吗?如果可以,使用
Dataset
的shuffle/batch/repeat方法比自己做这些常见的事情更不容易出错。查看详细信息,或者如果您发布生成器函数,我可能会更有用:)。我已经添加了read_wavfile代码,我只是尝试其他建议,包括精简数据集和原始数据。但是现在只有20个样本通过网络传递。以前,for
循环表示历元和
,而
循环负责在单个历元中将数据集的所有数据馈送到网络。谢谢,@Merlin1896。匆忙地发布了那个消息。我已经更新了我的答案。这里的主要想法是在每个训练阶段之后,而不是在每个训练示例中,将损失形象化。请尝试一下,如果结果和观察结果不同,请告诉我。干杯。@EkabaBisong我的数据集是个问题,洗牌有帮助,你是对的。不幸的是,在问题中添加信息意味着您的答案现在看起来有点奇怪,对此表示抱歉。
import scipy.io.wavfile as wave
import python_speech_features as psf
def getSpectrogram(path, winlen=0.025, winstep=0.01, NFFT=512):

    #open wav file
    (rate,sig) = wave.read(path)

    #get frames
    winfunc=lambda x:np.ones((x,))
    frames = psf.sigproc.framesig(sig, winlen*rate, winstep*rate, winfunc)

    #Magnitude Spectrogram
    magspec = np.rot90(psf.sigproc.magspec(frames, NFFT))

    #noise reduction (mean substract)
    magspec -= magspec.mean(axis=0)

    #normalize values between 0 and 1
    magspec -= magspec.min(axis=0)
    magspec /= magspec.max(axis=0)

    #show spec dimensions
    print magspec.shape    

    return magspec
#convert file if you need to
convert(filepath)

#get spectrogram
spec = getSpectrogram(filepath)