diff --git a/README_cn.md b/README_cn.md
index 994a4e2..ce88032 100644
--- a/README_cn.md
+++ b/README_cn.md
@@ -228,6 +228,6 @@ Parakeet 同时提供了示例模型的训练好的参数,可从下表中获
正在开发中。
-## 版权和许可
+## 版权和许可
Parakeet 以 [Apache-2.0 license](LICENSE) 提供。
diff --git a/doc/source/conf.py b/doc/source/conf.py
index f7d0af2..dd4a270 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
@@ -14,7 +28,6 @@
# import sys
# sys.path.insert(0, os.path.abspath('.'))
-
# -- Project information -----------------------------------------------------
project = 'parakeet'
@@ -24,7 +37,6 @@ author = 'parakeet-developers'
# The full version, including alpha/beta/rc tags
release = '0.2'
-
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
@@ -33,7 +45,7 @@ release = '0.2'
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.viewcode',
- "sphinx_rtd_theme",
+ "sphinx_rtd_theme",
'sphinx.ext.mathjax',
'numpydoc',
]
@@ -46,7 +58,6 @@ templates_path = ['_templates']
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
-
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
diff --git a/docs/config_cn.md b/docs/config_cn.md
index 2b8ce4c..29a80c6 100644
--- a/docs/config_cn.md
+++ b/docs/config_cn.md
@@ -18,7 +18,7 @@
常见的配置文件的格式有 `ini`, `yaml`, `toml`, `json` 等。
-`ini`
+`ini`
优点:简单,支持字符串插值等操作。
缺点:仅支持两层结构,值不带类型信息,解析的时候需要手动 cast。
@@ -102,11 +102,3 @@ optional arguments:
--opts ... options to overwrite --config file and the default
config, passing in KEY VALUE pairs
```
-
-
-
-
-
-
-
-
diff --git a/docs/data_cn.md b/docs/data_cn.md
index 4a7aab8..6ef6404 100644
--- a/docs/data_cn.md
+++ b/docs/data_cn.md
@@ -21,7 +21,7 @@
一般来说,我们将一个 Dataset 的子类看作是数据集和实验的具体需求之间的适配器。
-parakeet 还提供了若干个高阶的 Dataset 类,用于从已有的 Dataset 产生新的 Dataset.
+parakeet 还提供了若干个高阶的 Dataset 类,用于从已有的 Dataset 产生新的 Dataset.
1. 用于字段组合的有 TupleDataset, DictDataset;
2. 用于数据集切分合并的有 SliceDataset, SubsetDataset, ChainDataset;
@@ -137,7 +137,7 @@ class Transform(object):
self.processor = AudioProcessor(
sample_rate=22050,
n_fft=1024,
- win_length=1024,
+ win_length=1024,
hop_length=256,
f_max=8000)
self.normalizer = LogMagnitude()
@@ -167,7 +167,7 @@ ljspeech = TransformDataset(meta, transform)
当然也可以选择专门写一个转换脚本把转换后的数据集保存下来,然后再写一个适配的 Dataset 子类去加载这些保存的数据。实际这么做的效率会更高。
-接下来我们需要写一个可调用对象将多个样例组成批次。因为其中的 ids 和 mel 频谱是序列数据,所以我们需要进行 padding.
+接下来我们需要写一个可调用对象将多个样例组成批次。因为其中的 ids 和 mel 频谱是序列数据,所以我们需要进行 padding.
```python
class LJSpeechCollector(object):
@@ -197,10 +197,10 @@ def create_dataloader(source_path, valid_size, batch_size):
valid_set, train_set = dataset.split(lj, valid_size)
train_loader = DataLoader(
- train_set,
- return_list=False,
- batch_size=batch_size,
- shuffle=True,
+ train_set,
+ return_list=False,
+ batch_size=batch_size,
+ shuffle=True,
drop_last=True,
collate_fn=LJSpeechCollector())
valid_loader = DataLoader(
diff --git a/docs/experiment_cn.md b/docs/experiment_cn.md
index dc6a997..0596dda 100644
--- a/docs/experiment_cn.md
+++ b/docs/experiment_cn.md
@@ -72,4 +72,4 @@ def train(self):
```python
exp.run()
-```
\ No newline at end of file
+```
diff --git a/docs/experiment_guide_cn.md b/docs/experiment_guide_cn.md
index c5cc82e..8c9b89d 100644
--- a/docs/experiment_guide_cn.md
+++ b/docs/experiment_guide_cn.md
@@ -72,5 +72,3 @@ Dataset --(transform)--> Dataset --+
```
在这个软件源中包含了几个例子,可以在 [Parakeet/examples](../examples) 中查看。这些实验被作为样例提供给用户,可以直接运行。同时也欢迎用户添加新的模型和实验并为 `Parakeet` 贡献代码。
-
-
diff --git a/docs/installation_cn.md b/docs/installation_cn.md
index a861c86..030b721 100644
--- a/docs/installation_cn.md
+++ b/docs/installation_cn.md
@@ -31,7 +31,7 @@ python -m pip install paddlepaddle==2.0.0rc0 -i https://mirror.baidu.com/pypi/si
# ubuntu, debian
sudo apt-get install libsndfile1
-# centos, fedora,
+# centos, fedora,
sudo yum install libsndfile
# openSUSE
diff --git a/docs/overview_cn.md b/docs/overview_cn.md
index 40659af..06a9f93 100644
--- a/docs/overview_cn.md
+++ b/docs/overview_cn.md
@@ -9,10 +9,3 @@ Parakeet 为用户和开发者提供了
1. 可复用的模型以及常用的模块;
2. 从数据处理,模型训练到预测等一系列过程的完整实验;
3. 高质量的开箱即用模型。
-
-
-
-
-
-
-
diff --git a/examples/transformer_tts/config.py b/examples/transformer_tts/config.py
index fef9ed8..bcf8e90 100644
--- a/examples/transformer_tts/config.py
+++ b/examples/transformer_tts/config.py
@@ -1,21 +1,34 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from yacs.config import CfgNode as CN
_C = CN()
_C.data = CN(
dict(
- batch_size=16, # batch size
- valid_size=64, # the first N examples are reserved for validation
- sample_rate=22050, # Hz, sample rate
- n_fft=1024, # fft frame size
- win_length=1024, # window size
+ batch_size=16, # batch size
+ valid_size=64, # the first N examples are reserved for validation
+ sample_rate=22050, # Hz, sample rate
+ n_fft=1024, # fft frame size
+ win_length=1024, # window size
hop_length=256, # hop size between ajacent frame
- f_max=8000, # Hz, max frequency when converting to mel
+ f_max=8000, # Hz, max frequency when converting to mel
d_mel=80, # mel bands
- padding_idx=0, # text embedding's padding index
- mel_start_value=0.5, # value for starting frame
- mel_end_value=-0.5, # # value for ending frame
- )
-)
+ padding_idx=0, # text embedding's padding index
+ mel_start_value=0.5, # value for starting frame
+ mel_end_value=-0.5, # # value for ending frame
+ ))
_C.model = CN(
dict(
@@ -31,22 +44,21 @@ _C.model = CN(
postnet_kernel_size=5, # decoder postnet(cnn)'s kernel size
max_reduction_factor=10, # max_reduction factor
dropout=0.1, # global droput probability
- stop_loss_scale=8.0, # scaler for stop _loss
- decoder_prenet_dropout=0.5, # decoder prenet dropout probability
- )
-)
+ stop_loss_scale=8.0, # scaler for stop _loss
+ decoder_prenet_dropout=0.5, # decoder prenet dropout probability
+ ))
_C.training = CN(
dict(
- lr=1e-4, # learning rate
+ lr=1e-4, # learning rate
drop_n_heads=[[0, 0], [15000, 1]],
reduction_factor=[[0, 10], [80000, 4], [200000, 2]],
- plot_interval=1000, # plot attention and spectrogram
- valid_interval=1000, # validation
- save_interval=10000, # checkpoint
- max_iteration=900000, # max iteration to train
- )
-)
+ plot_interval=1000, # plot attention and spectrogram
+ valid_interval=1000, # validation
+ save_interval=10000, # checkpoint
+ max_iteration=900000, # max iteration to train
+ ))
+
def get_cfg_defaults():
"""Get a yacs CfgNode object with default values for my_project."""
diff --git a/examples/transformer_tts/ljspeech.py b/examples/transformer_tts/ljspeech.py
index 245b475..137db96 100644
--- a/examples/transformer_tts/ljspeech.py
+++ b/examples/transformer_tts/ljspeech.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import os
from pathlib import Path
import pickle
@@ -7,8 +21,10 @@ from paddle.io import Dataset, DataLoader
from parakeet.data.batch import batch_spec, batch_text_id
from parakeet.data import dataset
+
class LJSpeech(Dataset):
"""A simple dataset adaptor for the processed ljspeech dataset."""
+
def __init__(self, root):
self.root = Path(root).expanduser()
records = []
@@ -35,13 +51,13 @@ class Transform(object):
self.end_value = end_value
def __call__(self, example):
- ids, mel = example # ids already have and
+ ids, mel = example # ids already have and
ids = np.array(ids, dtype=np.int64)
# add start and end frame
- mel = np.pad(mel,
- [(0, 0), (1, 1)],
- mode='constant',
- constant_values=[(0, 0), (self.start_value, self.end_value)])
+ mel = np.pad(
+ mel, [(0, 0), (1, 1)],
+ mode='constant',
+ constant_values=[(0, 0), (self.start_value, self.end_value)])
stop_labels = np.ones([mel.shape[1]], dtype=np.int64)
stop_labels[-1] = 2
# actually this thing can also be done within the model
@@ -50,6 +66,7 @@ class Transform(object):
class LJSpeechCollector(object):
"""A simple callable to batch LJSpeech examples."""
+
def __init__(self, padding_idx=0, padding_value=0.):
self.padding_idx = padding_idx
self.padding_value = padding_value
@@ -67,15 +84,16 @@ class LJSpeechCollector(object):
def create_dataloader(config, source_path):
lj = LJSpeech(source_path)
- transform = Transform(config.data.mel_start_value, config.data.mel_end_value)
+ transform = Transform(config.data.mel_start_value,
+ config.data.mel_end_value)
lj = dataset.TransformDataset(lj, transform)
valid_set, train_set = dataset.split(lj, config.data.valid_size)
data_collator = LJSpeechCollector(padding_idx=config.data.padding_idx)
train_loader = DataLoader(
- train_set,
- batch_size=config.data.batch_size,
- shuffle=True,
+ train_set,
+ batch_size=config.data.batch_size,
+ shuffle=True,
drop_last=True,
collate_fn=data_collator)
valid_loader = DataLoader(
@@ -85,4 +103,3 @@ def create_dataloader(config, source_path):
drop_last=False,
collate_fn=data_collator)
return train_loader, valid_loader
-
diff --git a/examples/transformer_tts/preprocess.py b/examples/transformer_tts/preprocess.py
index 001f04c..2ba1985 100644
--- a/examples/transformer_tts/preprocess.py
+++ b/examples/transformer_tts/preprocess.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import os
import tqdm
import pickle
@@ -11,6 +25,7 @@ from parakeet.frontend import English
from config import get_cfg_defaults
+
def create_dataset(config, source_path, target_path, verbose=False):
# create output dir
target_path = Path(target_path).expanduser()
@@ -23,11 +38,11 @@ def create_dataset(config, source_path, target_path, verbose=False):
sample_rate=config.data.sample_rate,
n_fft=config.data.n_fft,
n_mels=config.data.d_mel,
- win_length=config.data.win_length,
+ win_length=config.data.win_length,
hop_length=config.data.hop_length,
f_max=config.data.f_max)
normalizer = LogMagnitude()
-
+
records = []
for (fname, text, _) in tqdm.tqdm(meta_data):
wav = processor.read_wav(fname)
@@ -42,12 +57,13 @@ def create_dataset(config, source_path, target_path, verbose=False):
np.save(mel_path / mel_name, mel)
if verbose:
print("save mel spectrograms into {}".format(mel_path))
-
+
# save meta data as pickle archive
with open(target_path / "metadata.pkl", 'wb') as f:
pickle.dump(records, f)
if verbose:
- print("saved metadata into {}".format(target_path / "metadata.pkl"))
+ print("saved metadata into {}".format(target_path /
+ "metadata.pkl"))
# also save meta data into text format for inspection
with open(target_path / "metadata.txt", 'wt') as f:
@@ -55,21 +71,31 @@ def create_dataset(config, source_path, target_path, verbose=False):
phoneme_str = "|".join(phonemes)
f.write("{}\t{}\t{}\n".format(mel_name, text, phoneme_str))
if verbose:
- print("saved metadata into {}".format(target_path / "metadata.txt"))
-
+ print("saved metadata into {}".format(target_path /
+ "metadata.txt"))
+
print("Done.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="create dataset")
- parser.add_argument("--config", type=str, metavar="FILE", help="extra config to overwrite the default config")
- parser.add_argument("--input", type=str, help="path of the ljspeech dataset")
- parser.add_argument("--output", type=str, help="path to save output dataset")
- parser.add_argument("--opts", nargs=argparse.REMAINDER,
+ parser.add_argument(
+ "--config",
+ type=str,
+ metavar="FILE",
+ help="extra config to overwrite the default config")
+ parser.add_argument(
+ "--input", type=str, help="path of the ljspeech dataset")
+ parser.add_argument(
+ "--output", type=str, help="path to save output dataset")
+ parser.add_argument(
+ "--opts",
+ nargs=argparse.REMAINDER,
help="options to overwrite --config file and the default config, passing in KEY VALUE pairs"
)
- parser.add_argument("-v", "--verbose", action="store_true", help="print msg")
-
+ parser.add_argument(
+ "-v", "--verbose", action="store_true", help="print msg")
+
config = get_cfg_defaults()
args = parser.parse_args()
if args.config:
diff --git a/examples/transformer_tts/synthesize.py b/examples/transformer_tts/synthesize.py
index b8f352f..6758819 100644
--- a/examples/transformer_tts/synthesize.py
+++ b/examples/transformer_tts/synthesize.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import argparse
import time
from pathlib import Path
@@ -13,21 +27,22 @@ from parakeet.utils.display import add_attention_plots
from config import get_cfg_defaults
+
@paddle.fluid.dygraph.no_grad
def main(config, args):
paddle.set_device(args.device)
# model
frontend = English()
- model = TransformerTTS.from_pretrained(
- frontend, config, args.checkpoint_path)
+ model = TransformerTTS.from_pretrained(frontend, config,
+ args.checkpoint_path)
model.eval()
# inputs
input_path = Path(args.input).expanduser()
- with open(input_path, "rt") as f:
+ with open(input_path, "rt") as f:
sentences = f.readlines()
-
+
output_dir = Path(args.output).expanduser()
output_dir.mkdir(parents=True, exist_ok=True)
@@ -38,22 +53,36 @@ def main(config, args):
mel_output = mel_output.T #(C, T)
np.save(str(output_dir / f"sentence_{i}"), mel_output)
if args.verbose:
- print("spectrogram saved at {}".format(output_dir / f"sentence_{i}.npy"))
+ print("spectrogram saved at {}".format(output_dir /
+ f"sentence_{i}.npy"))
+
if __name__ == "__main__":
config = get_cfg_defaults()
- parser = argparse.ArgumentParser(description="generate mel spectrogram with TransformerTTS.")
- parser.add_argument("--config", type=str, metavar="FILE", help="extra config to overwrite the default config")
- parser.add_argument("--checkpoint_path", type=str, help="path of the checkpoint to load.")
+ parser = argparse.ArgumentParser(
+ description="generate mel spectrogram with TransformerTTS.")
+ parser.add_argument(
+ "--config",
+ type=str,
+ metavar="FILE",
+ help="extra config to overwrite the default config")
+ parser.add_argument(
+ "--checkpoint_path", type=str, help="path of the checkpoint to load.")
parser.add_argument("--input", type=str, help="path of the text sentences")
parser.add_argument("--output", type=str, help="path to save outputs")
- parser.add_argument("--device", type=str, default="cpu", help="device type to use.")
- parser.add_argument("--opts", nargs=argparse.REMAINDER, help="options to overwrite --config file and the default config, passing in KEY VALUE pairs")
- parser.add_argument("-v", "--verbose", action="store_true", help="print msg")
-
+ parser.add_argument(
+ "--device", type=str, default="cpu", help="device type to use.")
+ parser.add_argument(
+ "--opts",
+ nargs=argparse.REMAINDER,
+ help="options to overwrite --config file and the default config, passing in KEY VALUE pairs"
+ )
+ parser.add_argument(
+ "-v", "--verbose", action="store_true", help="print msg")
+
args = parser.parse_args()
- if args.config:
+ if args.config:
config.merge_from_file(args.config)
if args.opts:
config.merge_from_list(args.opts)
diff --git a/examples/transformer_tts/train.py b/examples/transformer_tts/train.py
index 59ec7aa..b5ae11d 100644
--- a/examples/transformer_tts/train.py
+++ b/examples/transformer_tts/train.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import time
import logging
from pathlib import Path
@@ -19,12 +33,13 @@ from parakeet.training.experiment import ExperimentBase
from config import get_cfg_defaults
from ljspeech import LJSpeech, LJSpeechCollector, Transform
+
class Experiment(ExperimentBase):
def setup_model(self):
config = self.config
frontend = English()
model = TransformerTTS(
- frontend,
+ frontend,
d_encoder=config.model.d_encoder,
d_decoder=config.model.d_decoder,
d_mel=config.data.d_mel,
@@ -46,8 +61,7 @@ class Experiment(ExperimentBase):
beta1=0.9,
beta2=0.98,
epsilon=1e-9,
- parameters=model.parameters()
- )
+ parameters=model.parameters())
criterion = TransformerTTSLoss(config.model.stop_loss_scale)
drop_n_heads = scheduler.StepWise(config.training.drop_n_heads)
reduction_factor = scheduler.StepWise(config.training.reduction_factor)
@@ -63,21 +77,24 @@ class Experiment(ExperimentBase):
config = self.config
ljspeech_dataset = LJSpeech(args.data)
- transform = Transform(config.data.mel_start_value, config.data.mel_end_value)
- ljspeech_dataset = dataset.TransformDataset(ljspeech_dataset, transform)
- valid_set, train_set = dataset.split(ljspeech_dataset, config.data.valid_size)
+ transform = Transform(config.data.mel_start_value,
+ config.data.mel_end_value)
+ ljspeech_dataset = dataset.TransformDataset(ljspeech_dataset,
+ transform)
+ valid_set, train_set = dataset.split(ljspeech_dataset,
+ config.data.valid_size)
batch_fn = LJSpeechCollector(padding_idx=config.data.padding_idx)
-
+
if not self.parallel:
train_loader = DataLoader(
- train_set,
- batch_size=config.data.batch_size,
- shuffle=True,
+ train_set,
+ batch_size=config.data.batch_size,
+ shuffle=True,
drop_last=True,
collate_fn=batch_fn)
else:
sampler = DistributedBatchSampler(
- train_set,
+ train_set,
batch_size=config.data.batch_size,
num_replicas=dist.get_world_size(),
rank=dist.get_rank(),
@@ -95,11 +112,11 @@ class Experiment(ExperimentBase):
def compute_outputs(self, text, mel, stop_label):
model_core = self.model._layers if self.parallel else self.model
model_core.set_constants(
- self.reduction_factor(self.iteration),
+ self.reduction_factor(self.iteration),
self.drop_n_heads(self.iteration))
# TODO(chenfeiyu): we can combine these 2 slices
- mel_input = mel[:,:-1, :]
+ mel_input = mel[:, :-1, :]
reduced_mel_input = mel_input[:, ::model_core.r, :]
outputs = self.model(text, reduced_mel_input)
return outputs
@@ -115,11 +132,8 @@ class Experiment(ExperimentBase):
time_steps = mel_target.shape[1]
losses = self.criterion(
- mel_output[:,:time_steps, :],
- mel_intermediate[:,:time_steps, :],
- mel_target,
- stop_logits[:,:time_steps, :],
- stop_label_target)
+ mel_output[:, :time_steps, :], mel_intermediate[:, :time_steps, :],
+ mel_target, stop_logits[:, :time_steps, :], stop_label_target)
return losses
def train_batch(self):
@@ -133,7 +147,7 @@ class Experiment(ExperimentBase):
outputs = self.compute_outputs(text, mel, stop_label)
losses = self.compute_losses(batch, outputs)
loss = losses["loss"]
- loss.backward()
+ loss.backward()
self.optimizer.step()
iteration_time = time.time() - start
@@ -141,14 +155,17 @@ class Experiment(ExperimentBase):
# logging
msg = "Rank: {}, ".format(dist.get_rank())
msg += "step: {}, ".format(self.iteration)
- msg += "time: {:>.3f}s/{:>.3f}s, ".format(data_loader_time, iteration_time)
- msg += ', '.join('{}: {:>.6f}'.format(k, v) for k, v in losses_np.items())
+ msg += "time: {:>.3f}s/{:>.3f}s, ".format(data_loader_time,
+ iteration_time)
+ msg += ', '.join('{}: {:>.6f}'.format(k, v)
+ for k, v in losses_np.items())
self.logger.info(msg)
-
+
if dist.get_rank() == 0:
for k, v in losses_np.items():
- self.visualizer.add_scalar(f"train_loss/{k}", v, self.iteration)
-
+ self.visualizer.add_scalar(f"train_loss/{k}", v,
+ self.iteration)
+
@mp_tools.rank_zero_only
@paddle.no_grad()
def valid(self):
@@ -163,10 +180,9 @@ class Experiment(ExperimentBase):
if i < 2:
attention_weights = outputs["cross_attention_weights"]
display.add_multi_attention_plots(
- self.visualizer,
- f"valid_sentence_{i}_cross_attention_weights",
- attention_weights,
- self.iteration)
+ self.visualizer,
+ f"valid_sentence_{i}_cross_attention_weights",
+ attention_weights, self.iteration)
# write visual log
valid_losses = {k: np.mean(v) for k, v in valid_losses.items()}
@@ -191,7 +207,7 @@ if __name__ == "__main__":
config = get_cfg_defaults()
parser = default_argument_parser()
args = parser.parse_args()
- if args.config:
+ if args.config:
config.merge_from_file(args.config)
if args.opts:
config.merge_from_list(args.opts)
diff --git a/examples/waveflow/config.py b/examples/waveflow/config.py
index 97a877a..5ca2ba1 100644
--- a/examples/waveflow/config.py
+++ b/examples/waveflow/config.py
@@ -1,40 +1,52 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from yacs.config import CfgNode as CN
_C = CN()
_C.data = CN(
dict(
- batch_size=8, # batch size
- valid_size=16, # the first N examples are reserved for validation
- sample_rate=22050, # Hz, sample rate
- n_fft=1024, # fft frame size
- win_length=1024, # window size
+ batch_size=8, # batch size
+ valid_size=16, # the first N examples are reserved for validation
+ sample_rate=22050, # Hz, sample rate
+ n_fft=1024, # fft frame size
+ win_length=1024, # window size
hop_length=256, # hop size between ajacent frame
- f_max=8000, # Hz, max frequency when converting to mel
+ f_max=8000, # Hz, max frequency when converting to mel
n_mels=80, # mel bands
- clip_frames=65, # mel clip frames
- )
-)
+ clip_frames=65, # mel clip frames
+ ))
_C.model = CN(
dict(
upsample_factors=[16, 16],
- n_flows=8, # number of flows in WaveFlow
- n_layers=8, # number of conv block in each flow
- n_group=16, # folding factor of audio and spectrogram
- channels=128, # resiaudal channel in each flow
- kernel_size=[3, 3], # kernel size in each conv block
- sigma=1.0, # stddev of the random noise
- )
-)
+ n_flows=8, # number of flows in WaveFlow
+ n_layers=8, # number of conv block in each flow
+ n_group=16, # folding factor of audio and spectrogram
+ channels=128, # resiaudal channel in each flow
+ kernel_size=[3, 3], # kernel size in each conv block
+ sigma=1.0, # stddev of the random noise
+ ))
_C.training = CN(
dict(
- lr=2e-4, # learning rates
- valid_interval=1000, # validation
- save_interval=10000, # checkpoint
- max_iteration=3000000, # max iteration to train
- )
-)
+ lr=2e-4, # learning rates
+ valid_interval=1000, # validation
+ save_interval=10000, # checkpoint
+ max_iteration=3000000, # max iteration to train
+ ))
+
def get_cfg_defaults():
"""Get a yacs CfgNode object with default values for my_project."""
diff --git a/examples/waveflow/ljspeech.py b/examples/waveflow/ljspeech.py
index d7f5425..e07303a 100644
--- a/examples/waveflow/ljspeech.py
+++ b/examples/waveflow/ljspeech.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import os
from pathlib import Path
import pickle
@@ -9,19 +23,20 @@ from parakeet.data.batch import batch_spec, batch_wav
from parakeet.data import dataset
from parakeet.audio import AudioProcessor
+
class LJSpeech(Dataset):
"""A simple dataset adaptor for the processed ljspeech dataset."""
+
def __init__(self, root):
self.root = Path(root).expanduser()
meta_data = pandas.read_csv(
str(self.root / "metadata.csv"),
sep="\t",
header=None,
- names=["fname", "frames", "samples"]
- )
-
+ names=["fname", "frames", "samples"])
+
records = []
- for row in meta_data.itertuples() :
+ for row in meta_data.itertuples():
mel_path = str(self.root / "mel" / (row.fname + ".npy"))
wav_path = str(self.root / "wav" / (row.fname + ".npy"))
records.append((mel_path, wav_path))
@@ -39,6 +54,7 @@ class LJSpeech(Dataset):
class LJSpeechCollector(object):
"""A simple callable to batch LJSpeech examples."""
+
def __init__(self, padding_value=0.):
self.padding_value = padding_value
@@ -52,9 +68,9 @@ class LJSpeechCollector(object):
class LJSpeechClipCollector(object):
def __init__(self, clip_frames=65, hop_length=256):
- self.clip_frames = clip_frames
+ self.clip_frames = clip_frames
self.hop_length = hop_length
-
+
def __call__(self, examples):
mels = []
wavs = []
@@ -70,9 +86,7 @@ class LJSpeechClipCollector(object):
mel, wav = example
frames = mel.shape[-1]
start = np.random.randint(0, frames - self.clip_frames)
- mel_clip = mel[:, start: start + self.clip_frames]
- wav_clip = wav[start * self.hop_length: (start + self.clip_frames) * self.hop_length]
+ mel_clip = mel[:, start:start + self.clip_frames]
+ wav_clip = wav[start * self.hop_length:(start + self.clip_frames) *
+ self.hop_length]
return mel_clip, wav_clip
-
-
-
diff --git a/examples/waveflow/preprocess.py b/examples/waveflow/preprocess.py
index d4bdc8e..ac6d62e 100644
--- a/examples/waveflow/preprocess.py
+++ b/examples/waveflow/preprocess.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import os
import tqdm
import csv
@@ -86,12 +100,8 @@ def create_dataset(config, input_dir, output_dir, verbose=True):
output_dir = Path(output_dir).expanduser()
output_dir.mkdir(exist_ok=True)
- transform = Transform(
- config.sample_rate,
- config.n_fft,
- config.win_length,
- config.hop_length,
- config.n_mels)
+ transform = Transform(config.sample_rate, config.n_fft, config.win_length,
+ config.hop_length, config.n_mels)
file_names = []
for example in tqdm.tqdm(dataset):
@@ -107,23 +117,35 @@ def create_dataset(config, input_dir, output_dir, verbose=True):
np.save(str(mel_dir / base_name), mel)
file_names.append((base_name, mel.shape[-1], audio.shape[-1]))
-
+
meta_data = pd.DataFrame.from_records(file_names)
- meta_data.to_csv(str(output_dir / "metadata.csv"), sep="\t", index=None, header=None)
- print("saved meta data in to {}".format(os.path.join(output_dir, "metadata.csv")))
+ meta_data.to_csv(
+ str(output_dir / "metadata.csv"), sep="\t", index=None, header=None)
+ print("saved meta data in to {}".format(
+ os.path.join(output_dir, "metadata.csv")))
print("Done!")
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="create dataset")
- parser.add_argument("--config", type=str, metavar="FILE", help="extra config to overwrite the default config")
- parser.add_argument("--input", type=str, help="path of the ljspeech dataset")
- parser.add_argument("--output", type=str, help="path to save output dataset")
- parser.add_argument("--opts", nargs=argparse.REMAINDER,
+ parser.add_argument(
+ "--config",
+ type=str,
+ metavar="FILE",
+ help="extra config to overwrite the default config")
+ parser.add_argument(
+ "--input", type=str, help="path of the ljspeech dataset")
+ parser.add_argument(
+ "--output", type=str, help="path to save output dataset")
+ parser.add_argument(
+ "--opts",
+ nargs=argparse.REMAINDER,
help="options to overwrite --config file and the default config, passing in KEY VALUE pairs"
)
- parser.add_argument("-v", "--verbose", action="store_true", help="print msg")
-
+ parser.add_argument(
+ "-v", "--verbose", action="store_true", help="print msg")
+
config = get_cfg_defaults()
args = parser.parse_args()
if args.config:
diff --git a/examples/waveflow/synthesize.py b/examples/waveflow/synthesize.py
index 1856eb2..45c751a 100644
--- a/examples/waveflow/synthesize.py
+++ b/examples/waveflow/synthesize.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import argparse
import numpy as np
import soundfile as sf
@@ -8,9 +22,9 @@ import parakeet
from parakeet.models.waveflow import UpsampleNet, WaveFlow, ConditionalWaveFlow
from parakeet.utils import layer_tools, checkpoint
-
from config import get_cfg_defaults
+
def main(config, args):
paddle.set_device(args.device)
model = ConditionalWaveFlow.from_pretrained(config, args.checkpoint_path)
@@ -23,7 +37,8 @@ def main(config, args):
for file_path in mel_dir.iterdir():
mel = np.load(str(file_path))
audio = model.predict(mel)
- audio_path = output_dir / (os.path.splitext(file_path.name)[0] + ".wav")
+ audio_path = output_dir / (
+ os.path.splitext(file_path.name)[0] + ".wav")
sf.write(audio_path, audio, config.data.sample_rate)
print("[synthesize] {} -> {}".format(file_path, audio_path))
@@ -31,17 +46,32 @@ def main(config, args):
if __name__ == "__main__":
config = get_cfg_defaults()
- parser = argparse.ArgumentParser(description="generate mel spectrogram with TransformerTTS.")
- parser.add_argument("--config", type=str, metavar="FILE", help="extra config to overwrite the default config")
- parser.add_argument("--checkpoint_path", type=str, help="path of the checkpoint to load.")
- parser.add_argument("--input", type=str, help="path of directory containing mel spectrogram (in .npy format)")
+ parser = argparse.ArgumentParser(
+ description="generate mel spectrogram with TransformerTTS.")
+ parser.add_argument(
+ "--config",
+ type=str,
+ metavar="FILE",
+ help="extra config to overwrite the default config")
+ parser.add_argument(
+ "--checkpoint_path", type=str, help="path of the checkpoint to load.")
+ parser.add_argument(
+ "--input",
+ type=str,
+ help="path of directory containing mel spectrogram (in .npy format)")
parser.add_argument("--output", type=str, help="path to save outputs")
- parser.add_argument("--device", type=str, default="cpu", help="device type to use.")
- parser.add_argument("--opts", nargs=argparse.REMAINDER, help="options to overwrite --config file and the default config, passing in KEY VALUE pairs")
- parser.add_argument("-v", "--verbose", action="store_true", help="print msg")
-
+ parser.add_argument(
+ "--device", type=str, default="cpu", help="device type to use.")
+ parser.add_argument(
+ "--opts",
+ nargs=argparse.REMAINDER,
+ help="options to overwrite --config file and the default config, passing in KEY VALUE pairs"
+ )
+ parser.add_argument(
+ "-v", "--verbose", action="store_true", help="print msg")
+
args = parser.parse_args()
- if args.config:
+ if args.config:
config.merge_from_file(args.config)
if args.opts:
config.merge_from_list(args.opts)
@@ -49,4 +79,4 @@ if __name__ == "__main__":
print(config)
print(args)
- main(config, args)
\ No newline at end of file
+ main(config, args)
diff --git a/examples/waveflow/train.py b/examples/waveflow/train.py
index 1cd68f0..443cc8b 100644
--- a/examples/waveflow/train.py
+++ b/examples/waveflow/train.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import time
from pathlib import Path
import numpy as np
@@ -34,7 +48,8 @@ class Experiment(ExperimentBase):
if self.parallel > 1:
model = paddle.DataParallel(model)
- optimizer = paddle.optimizer.Adam(config.training.lr, parameters=model.parameters())
+ optimizer = paddle.optimizer.Adam(
+ config.training.lr, parameters=model.parameters())
criterion = WaveFlowLoss(sigma=config.model.sigma)
self.model = model
@@ -46,20 +61,22 @@ class Experiment(ExperimentBase):
args = self.args
ljspeech_dataset = LJSpeech(args.data)
- valid_set, train_set = dataset.split(ljspeech_dataset, config.data.valid_size)
+ valid_set, train_set = dataset.split(ljspeech_dataset,
+ config.data.valid_size)
+
+ batch_fn = LJSpeechClipCollector(config.data.clip_frames,
+ config.data.hop_length)
- batch_fn = LJSpeechClipCollector(config.data.clip_frames, config.data.hop_length)
-
if not self.parallel:
train_loader = DataLoader(
- train_set,
- batch_size=config.data.batch_size,
- shuffle=True,
+ train_set,
+ batch_size=config.data.batch_size,
+ shuffle=True,
drop_last=True,
collate_fn=batch_fn)
else:
sampler = DistributedBatchSampler(
- train_set,
+ train_set,
batch_size=config.data.batch_size,
num_replicas=dist.get_world_size(),
rank=dist.get_rank(),
@@ -71,7 +88,7 @@ class Experiment(ExperimentBase):
valid_batch_fn = LJSpeechCollector()
valid_loader = DataLoader(
valid_set, batch_size=1, collate_fn=valid_batch_fn)
-
+
self.train_loader = train_loader
self.valid_loader = valid_loader
@@ -90,17 +107,19 @@ class Experiment(ExperimentBase):
mel, wav = batch
z, log_det_jocobian = self.compute_outputs(mel, wav)
loss = self.criterion(z, log_det_jocobian)
- loss.backward()
+ loss.backward()
self.optimizer.step()
iteration_time = time.time() - start
loss_value = float(loss)
msg = "Rank: {}, ".format(dist.get_rank())
msg += "step: {}, ".format(self.iteration)
- msg += "time: {:>.3f}s/{:>.3f}s, ".format(data_loader_time, iteration_time)
+ msg += "time: {:>.3f}s/{:>.3f}s, ".format(data_loader_time,
+ iteration_time)
msg += "loss: {:>.6f}".format(loss_value)
self.logger.info(msg)
- self.visualizer.add_scalar("train/loss", loss_value, global_step=self.iteration)
+ self.visualizer.add_scalar(
+ "train/loss", loss_value, global_step=self.iteration)
@mp_tools.rank_zero_only
@paddle.no_grad()
@@ -112,7 +131,8 @@ class Experiment(ExperimentBase):
loss = self.criterion(z, log_det_jocobian)
valid_losses.append(float(loss))
valid_loss = np.mean(valid_losses)
- self.visualizer.add_scalar("valid/loss", valid_loss, global_step=self.iteration)
+ self.visualizer.add_scalar(
+ "valid/loss", valid_loss, global_step=self.iteration)
def main_sp(config, args):
@@ -132,7 +152,7 @@ if __name__ == "__main__":
config = get_cfg_defaults()
parser = default_argument_parser()
args = parser.parse_args()
- if args.config:
+ if args.config:
config.merge_from_file(args.config)
if args.opts:
config.merge_from_list(args.opts)
diff --git a/examples/wavenet/config.py b/examples/wavenet/config.py
index 58f9beb..658d416 100644
--- a/examples/wavenet/config.py
+++ b/examples/wavenet/config.py
@@ -1,19 +1,32 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from yacs.config import CfgNode as CN
_C = CN()
_C.data = CN(
dict(
- batch_size=8, # batch size
- valid_size=16, # the first N examples are reserved for validation
- sample_rate=22050, # Hz, sample rate
- n_fft=2048, # fft frame size
- win_length=1024, # window size
+ batch_size=8, # batch size
+ valid_size=16, # the first N examples are reserved for validation
+ sample_rate=22050, # Hz, sample rate
+ n_fft=2048, # fft frame size
+ win_length=1024, # window size
hop_length=256, # hop size between ajacent frame
# f_max=8000, # Hz, max frequency when converting to mel
n_mels=80, # mel bands
- train_clip_seconds=0.5, # audio clip length(in seconds)
- )
-)
+ train_clip_seconds=0.5, # audio clip length(in seconds)
+ ))
_C.model = CN(
dict(
@@ -21,24 +34,22 @@ _C.model = CN(
n_stack=3,
n_loop=10,
filter_size=2,
- residual_channels=128, # resiaudal channel in each flow
+ residual_channels=128, # resiaudal channel in each flow
loss_type="mog",
- output_dim=3, # single gaussian
- log_scale_min=-9.0,
- )
-)
+ output_dim=3, # single gaussian
+ log_scale_min=-9.0, ))
_C.training = CN(
dict(
- lr=1e-3, # learning rates
- anneal_rate=0.5, # learning rate decay rate
- anneal_interval=200000, # decrese lr by annel_rate every anneal_interval steps
- valid_interval=1000, # validation
- save_interval=10000, # checkpoint
- max_iteration=3000000, # max iteration to train
- gradient_max_norm=100.0 # global norm of gradients
- )
-)
+ lr=1e-3, # learning rates
+ anneal_rate=0.5, # learning rate decay rate
+ anneal_interval=200000, # decrese lr by annel_rate every anneal_interval steps
+ valid_interval=1000, # validation
+ save_interval=10000, # checkpoint
+ max_iteration=3000000, # max iteration to train
+ gradient_max_norm=100.0 # global norm of gradients
+ ))
+
def get_cfg_defaults():
"""Get a yacs CfgNode object with default values for my_project."""
diff --git a/examples/wavenet/ljspeech.py b/examples/wavenet/ljspeech.py
index 18dc388..d1d3c67 100644
--- a/examples/wavenet/ljspeech.py
+++ b/examples/wavenet/ljspeech.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import os
from pathlib import Path
import pickle
@@ -9,19 +23,20 @@ from parakeet.data.batch import batch_spec, batch_wav
from parakeet.data import dataset
from parakeet.audio import AudioProcessor
+
class LJSpeech(Dataset):
"""A simple dataset adaptor for the processed ljspeech dataset."""
+
def __init__(self, root):
self.root = Path(root).expanduser()
meta_data = pandas.read_csv(
str(self.root / "metadata.csv"),
sep="\t",
header=None,
- names=["fname", "frames", "samples"]
- )
-
+ names=["fname", "frames", "samples"])
+
records = []
- for row in meta_data.itertuples() :
+ for row in meta_data.itertuples():
mel_path = str(self.root / "mel" / (row.fname + ".npy"))
wav_path = str(self.root / "wav" / (row.fname + ".npy"))
records.append((mel_path, wav_path))
@@ -39,6 +54,7 @@ class LJSpeech(Dataset):
class LJSpeechCollector(object):
"""A simple callable to batch LJSpeech examples."""
+
def __init__(self, padding_value=0.):
self.padding_value = padding_value
@@ -48,15 +64,15 @@ class LJSpeechCollector(object):
wavs = [example[1] for example in examples]
mels = batch_spec(mels, pad_value=self.padding_value)
wavs = batch_wav(wavs, pad_value=self.padding_value)
- audio_starts = np.zeros((batch_size,), dtype=np.int64)
+ audio_starts = np.zeros((batch_size, ), dtype=np.int64)
return mels, wavs, audio_starts
class LJSpeechClipCollector(object):
def __init__(self, clip_frames=65, hop_length=256):
- self.clip_frames = clip_frames
+ self.clip_frames = clip_frames
self.hop_length = hop_length
-
+
def __call__(self, examples):
mels = []
wavs = []
@@ -75,7 +91,8 @@ class LJSpeechClipCollector(object):
mel, wav = example
frames = mel.shape[-1]
start = np.random.randint(0, frames - self.clip_frames)
- wav_clip = wav[start * self.hop_length: (start + self.clip_frames) * self.hop_length]
+ wav_clip = wav[start * self.hop_length:(start + self.clip_frames) *
+ self.hop_length]
return mel, wav_clip, start
@@ -132,7 +149,3 @@ class DataCollector(object):
audios = np.array(audios, dtype=np.float32)
audio_starts = np.array(audio_starts, dtype=np.int64)
return audios, mels, audio_starts
-
-
-
-
diff --git a/examples/wavenet/preprocess.py b/examples/wavenet/preprocess.py
index 29b140c..cc83727 100644
--- a/examples/wavenet/preprocess.py
+++ b/examples/wavenet/preprocess.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import os
import tqdm
import csv
@@ -23,7 +37,7 @@ class Transform(object):
self.win_length = win_length
self.hop_length = hop_length
self.n_mels = n_mels
-
+
self.spec_normalizer = UnitMagnitude(min=1e-5)
def __call__(self, example):
@@ -87,12 +101,8 @@ def create_dataset(config, input_dir, output_dir, verbose=True):
output_dir = Path(output_dir).expanduser()
output_dir.mkdir(exist_ok=True)
- transform = Transform(
- config.sample_rate,
- config.n_fft,
- config.win_length,
- config.hop_length,
- config.n_mels)
+ transform = Transform(config.sample_rate, config.n_fft, config.win_length,
+ config.hop_length, config.n_mels)
file_names = []
for example in tqdm.tqdm(dataset):
@@ -108,23 +118,35 @@ def create_dataset(config, input_dir, output_dir, verbose=True):
np.save(str(mel_dir / base_name), mel)
file_names.append((base_name, mel.shape[-1], audio.shape[-1]))
-
+
meta_data = pd.DataFrame.from_records(file_names)
- meta_data.to_csv(str(output_dir / "metadata.csv"), sep="\t", index=None, header=None)
- print("saved meta data in to {}".format(os.path.join(output_dir, "metadata.csv")))
+ meta_data.to_csv(
+ str(output_dir / "metadata.csv"), sep="\t", index=None, header=None)
+ print("saved meta data in to {}".format(
+ os.path.join(output_dir, "metadata.csv")))
print("Done!")
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="create dataset")
- parser.add_argument("--config", type=str, metavar="FILE", help="extra config to overwrite the default config")
- parser.add_argument("--input", type=str, help="path of the ljspeech dataset")
- parser.add_argument("--output", type=str, help="path to save output dataset")
- parser.add_argument("--opts", nargs=argparse.REMAINDER,
+ parser.add_argument(
+ "--config",
+ type=str,
+ metavar="FILE",
+ help="extra config to overwrite the default config")
+ parser.add_argument(
+ "--input", type=str, help="path of the ljspeech dataset")
+ parser.add_argument(
+ "--output", type=str, help="path to save output dataset")
+ parser.add_argument(
+ "--opts",
+ nargs=argparse.REMAINDER,
help="options to overwrite --config file and the default config, passing in KEY VALUE pairs"
)
- parser.add_argument("-v", "--verbose", action="store_true", help="print msg")
-
+ parser.add_argument(
+ "-v", "--verbose", action="store_true", help="print msg")
+
config = get_cfg_defaults()
args = parser.parse_args()
if args.config:
diff --git a/examples/wavenet/synthesize.py b/examples/wavenet/synthesize.py
index 80b96a2..c5a69fe 100644
--- a/examples/wavenet/synthesize.py
+++ b/examples/wavenet/synthesize.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import argparse
import numpy as np
import soundfile as sf
@@ -10,6 +24,7 @@ from parakeet.utils import layer_tools, checkpoint
from config import get_cfg_defaults
+
def main(config, args):
paddle.set_device(args.device)
model = ConditionalWaveNet.from_pretrained(config, args.checkpoint_path)
@@ -22,7 +37,8 @@ def main(config, args):
for file_path in mel_dir.iterdir():
mel = np.load(str(file_path))
audio = model.predict(mel)
- audio_path = output_dir / (os.path.splitext(file_path.name)[0] + ".wav")
+ audio_path = output_dir / (
+ os.path.splitext(file_path.name)[0] + ".wav")
sf.write(audio_path, audio, config.data.sample_rate)
print("[synthesize] {} -> {}".format(file_path, audio_path))
@@ -30,17 +46,32 @@ def main(config, args):
if __name__ == "__main__":
config = get_cfg_defaults()
- parser = argparse.ArgumentParser(description="generate mel spectrogram with TransformerTTS.")
- parser.add_argument("--config", type=str, metavar="FILE", help="extra config to overwrite the default config")
- parser.add_argument("--checkpoint_path", type=str, help="path of the checkpoint to load.")
- parser.add_argument("--input", type=str, help="path of directory containing mel spectrogram (in .npy format)")
+ parser = argparse.ArgumentParser(
+ description="generate mel spectrogram with TransformerTTS.")
+ parser.add_argument(
+ "--config",
+ type=str,
+ metavar="FILE",
+ help="extra config to overwrite the default config")
+ parser.add_argument(
+ "--checkpoint_path", type=str, help="path of the checkpoint to load.")
+ parser.add_argument(
+ "--input",
+ type=str,
+ help="path of directory containing mel spectrogram (in .npy format)")
parser.add_argument("--output", type=str, help="path to save outputs")
- parser.add_argument("--device", type=str, default="cpu", help="device type to use.")
- parser.add_argument("--opts", nargs=argparse.REMAINDER, help="options to overwrite --config file and the default config, passing in KEY VALUE pairs")
- parser.add_argument("-v", "--verbose", action="store_true", help="print msg")
-
+ parser.add_argument(
+ "--device", type=str, default="cpu", help="device type to use.")
+ parser.add_argument(
+ "--opts",
+ nargs=argparse.REMAINDER,
+ help="options to overwrite --config file and the default config, passing in KEY VALUE pairs"
+ )
+ parser.add_argument(
+ "-v", "--verbose", action="store_true", help="print msg")
+
args = parser.parse_args()
- if args.config:
+ if args.config:
config.merge_from_file(args.config)
if args.opts:
config.merge_from_list(args.opts)
@@ -48,4 +79,4 @@ if __name__ == "__main__":
print(config)
print(args)
- main(config, args)
\ No newline at end of file
+ main(config, args)
diff --git a/examples/wavenet/train.py b/examples/wavenet/train.py
index 77c54e3..8e9bc0e 100644
--- a/examples/wavenet/train.py
+++ b/examples/wavenet/train.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import time
from pathlib import Path
import math
@@ -26,7 +40,7 @@ class Experiment(ExperimentBase):
config = self.config
model = ConditionalWaveNet(
upsample_factors=config.model.upsample_factors,
- n_stack=config.model.n_stack,
+ n_stack=config.model.n_stack,
n_loop=config.model.n_loop,
residual_channels=config.model.residual_channels,
output_dim=config.model.output_dim,
@@ -39,13 +53,13 @@ class Experiment(ExperimentBase):
model = paddle.DataParallel(model)
lr_scheduler = paddle.optimizer.lr.StepDecay(
- config.training.lr,
- config.training.anneal_interval,
+ config.training.lr, config.training.anneal_interval,
config.training.anneal_rate)
optimizer = paddle.optimizer.Adam(
lr_scheduler,
parameters=model.parameters(),
- grad_clip=paddle.nn.ClipGradByGlobalNorm(config.training.gradient_max_norm))
+ grad_clip=paddle.nn.ClipGradByGlobalNorm(
+ config.training.gradient_max_norm))
self.model = model
self.model_core = model._layer if self.parallel else model
@@ -56,7 +70,8 @@ class Experiment(ExperimentBase):
args = self.args
ljspeech_dataset = LJSpeech(args.data)
- valid_set, train_set = dataset.split(ljspeech_dataset, config.data.valid_size)
+ valid_set, train_set = dataset.split(ljspeech_dataset,
+ config.data.valid_size)
# convolutional net's causal padding size
context_size = config.model.n_stack \
@@ -66,20 +81,21 @@ class Experiment(ExperimentBase):
# frames used to compute loss
frames_per_second = config.data.sample_rate // config.data.hop_length
- train_clip_frames = math.ceil(config.data.train_clip_seconds * frames_per_second)
-
+ train_clip_frames = math.ceil(config.data.train_clip_seconds *
+ frames_per_second)
+
num_frames = train_clip_frames + context_frames
batch_fn = LJSpeechClipCollector(num_frames, config.data.hop_length)
if not self.parallel:
train_loader = DataLoader(
- train_set,
- batch_size=config.data.batch_size,
- shuffle=True,
+ train_set,
+ batch_size=config.data.batch_size,
+ shuffle=True,
drop_last=True,
collate_fn=batch_fn)
else:
sampler = DistributedBatchSampler(
- train_set,
+ train_set,
batch_size=config.data.batch_size,
shuffle=True,
drop_last=True)
@@ -89,7 +105,7 @@ class Experiment(ExperimentBase):
valid_batch_fn = LJSpeechCollector()
valid_loader = DataLoader(
valid_set, batch_size=1, collate_fn=valid_batch_fn)
-
+
self.train_loader = train_loader
self.valid_loader = valid_loader
@@ -101,20 +117,22 @@ class Experiment(ExperimentBase):
self.model.train()
self.optimizer.clear_grad()
mel, wav, audio_starts = batch
-
+
y = self.model(wav, mel, audio_starts)
loss = self.model.loss(y, wav)
- loss.backward()
+ loss.backward()
self.optimizer.step()
iteration_time = time.time() - start
loss_value = float(loss)
msg = "Rank: {}, ".format(dist.get_rank())
msg += "step: {}, ".format(self.iteration)
- msg += "time: {:>.3f}s/{:>.3f}s, ".format(data_loader_time, iteration_time)
+ msg += "time: {:>.3f}s/{:>.3f}s, ".format(data_loader_time,
+ iteration_time)
msg += "loss: {:>.6f}".format(loss_value)
self.logger.info(msg)
- self.visualizer.add_scalar("train/loss", loss_value, global_step=self.iteration)
+ self.visualizer.add_scalar(
+ "train/loss", loss_value, global_step=self.iteration)
@mp_tools.rank_zero_only
@paddle.no_grad()
@@ -126,7 +144,8 @@ class Experiment(ExperimentBase):
loss = self.model.loss(y, wav)
valid_losses.append(float(loss))
valid_loss = np.mean(valid_losses)
- self.visualizer.add_scalar("valid/loss", valid_loss, global_step=self.iteration)
+ self.visualizer.add_scalar(
+ "valid/loss", valid_loss, global_step=self.iteration)
def main_sp(config, args):
@@ -146,7 +165,7 @@ if __name__ == "__main__":
config = get_cfg_defaults()
parser = default_argument_parser()
args = parser.parse_args()
- if args.config:
+ if args.config:
config.merge_from_file(args.config)
if args.opts:
config.merge_from_list(args.opts)
diff --git a/parakeet/audio/audio.py b/parakeet/audio/audio.py
index 93d4e6b..3795111 100644
--- a/parakeet/audio/audio.py
+++ b/parakeet/audio/audio.py
@@ -18,15 +18,16 @@ import numpy as np
__all__ = ["AudioProcessor"]
+
class AudioProcessor(object):
def __init__(self,
- sample_rate:int,
- n_fft:int,
- win_length:int,
- hop_length:int,
- n_mels:int=80,
- f_min:int=0,
- f_max:int=None,
+ sample_rate: int,
+ n_fft: int,
+ win_length: int,
+ hop_length: int,
+ n_mels: int=80,
+ f_min: int=0,
+ f_max: int=None,
window="hann",
center=True,
pad_mode="reflect"):
@@ -40,7 +41,7 @@ class AudioProcessor(object):
self.window = window
self.center = center
self.pad_mode = pad_mode
-
+
# mel
self.n_mels = n_mels
self.f_min = f_min
@@ -48,19 +49,18 @@ class AudioProcessor(object):
self.mel_filter = self._create_mel_filter()
self.inv_mel_filter = np.linalg.pinv(self.mel_filter)
-
+
def _create_mel_filter(self):
- mel_filter = librosa.filters.mel(
- self.sample_rate,
- self.n_fft,
- n_mels=self.n_mels,
- fmin=self.f_min,
- fmax=self.f_max)
+ mel_filter = librosa.filters.mel(self.sample_rate,
+ self.n_fft,
+ n_mels=self.n_mels,
+ fmin=self.f_min,
+ fmax=self.f_max)
return mel_filter
def read_wav(self, filename):
# resampling may occur
- wav, _ = librosa.load(filename, sr=self.sample_rate)
+ wav, _ = librosa.load(filename, sr=self.sample_rate)
return wav
def write_wav(self, path, wav):
@@ -69,7 +69,7 @@ class AudioProcessor(object):
def stft(self, wav):
D = librosa.core.stft(
wav,
- n_fft = self.n_fft,
+ n_fft=self.n_fft,
hop_length=self.hop_length,
win_length=self.win_length,
window=self.window,
diff --git a/parakeet/audio/spec_normalizer.py b/parakeet/audio/spec_normalizer.py
index 08cea1b..069c453 100644
--- a/parakeet/audio/spec_normalizer.py
+++ b/parakeet/audio/spec_normalizer.py
@@ -1,3 +1,16 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
"""
This modules contains normalizers for spectrogram magnitude.
@@ -19,22 +32,24 @@ __all__ = ["NormalizerBase", "LogMagnitude", "UnitMagnitude"]
class NormalizerBase(object):
def transform(self, spec):
raise NotImplementedError("transform must be implemented")
-
+
def inverse(self, normalized):
raise NotImplementedError("inverse must be implemented")
+
class LogMagnitude(NormalizerBase):
"""
This is a simple normalizer used in Waveglow, Waveflow, tacotron2...
"""
+
def __init__(self, min=1e-7):
self.min = min
-
+
def transform(self, x):
x = np.maximum(x, self.min)
x = np.log(x)
return x
-
+
def inverse(self, x):
return np.exp(x)
@@ -44,15 +59,16 @@ class UnitMagnitude(NormalizerBase):
"""
This is the normalizer used in the
"""
+
def __init__(self, min=1e-5):
self.min = min
-
+
def transform(self, x):
db_scale = 20 * np.log10(np.maximum(self.min, x)) - 20
normalized = (db_scale + 100) / 100
clipped = np.clip(normalized, 0, 1)
return clipped
-
+
def inverse(self, x):
denormalized = np.clip(x, 0, 1) * 100 - 100
out = np.exp((denormalized + 20) / 20 * np.log(10))
diff --git a/parakeet/data/batch.py b/parakeet/data/batch.py
index 1551124..4c5be61 100644
--- a/parakeet/data/batch.py
+++ b/parakeet/data/batch.py
@@ -18,10 +18,15 @@ Batch functions for text sequences, audio and spectrograms are provided.
import numpy as np
__all__ = [
- "batch_text_id", "batch_wav", "batch_spec",
- "TextIDBatcher", "WavBatcher", "SpecBatcher",
+ "batch_text_id",
+ "batch_wav",
+ "batch_spec",
+ "TextIDBatcher",
+ "WavBatcher",
+ "SpecBatcher",
]
+
class TextIDBatcher(object):
"""A wrapper class for `batch_text_id`."""
@@ -99,8 +104,8 @@ def batch_wav(minibatch, pad_value=0., dtype=np.float32):
pad_len = max_len - example.shape[-1]
batch.append(
np.pad(example, [(0, pad_len)],
- mode='constant',
- constant_values=pad_value))
+ mode='constant',
+ constant_values=pad_value))
return np.array(batch, dtype=dtype)
@@ -113,7 +118,11 @@ class SpecBatcher(object):
self.time_major = time_major
def __call__(self, minibatch):
- out = batch_spec(minibatch, pad_value=self.pad_value, time_major=self.time_major, dtype=self.dtype)
+ out = batch_spec(
+ minibatch,
+ pad_value=self.pad_value,
+ time_major=self.time_major,
+ dtype=self.dtype)
return out
@@ -130,7 +139,8 @@ def batch_spec(minibatch, pad_value=0., time_major=False, dtype=np.float32):
"""
# assume (F, T) or (T, F)
peek_example = minibatch[0]
- assert len(peek_example.shape) == 2, "we only handles mono channel spectrogram"
+ assert len(
+ peek_example.shape) == 2, "we only handles mono channel spectrogram"
# assume (F, n_frame) or (n_frame, F)
time_idx = 0 if time_major else -1
@@ -143,11 +153,11 @@ def batch_spec(minibatch, pad_value=0., time_major=False, dtype=np.float32):
if time_major:
batch.append(
np.pad(example, [(0, pad_len), (0, 0)],
- mode='constant',
- constant_values=pad_value))
+ mode='constant',
+ constant_values=pad_value))
else:
batch.append(
np.pad(example, [(0, 0), (0, pad_len)],
- mode='constant',
- constant_values=pad_value))
+ mode='constant',
+ constant_values=pad_value))
return np.array(batch, dtype=dtype)
diff --git a/parakeet/data/dataset.py b/parakeet/data/dataset.py
index de9b40c..a188767 100644
--- a/parakeet/data/dataset.py
+++ b/parakeet/data/dataset.py
@@ -17,17 +17,25 @@ import paddle
from paddle.io import Dataset
__all__ = [
- "split", "TransformDataset", "CacheDataset", "TupleDataset",
- "DictDataset", "SliceDataset", "SubsetDataset", "FilterDataset",
+ "split",
+ "TransformDataset",
+ "CacheDataset",
+ "TupleDataset",
+ "DictDataset",
+ "SliceDataset",
+ "SubsetDataset",
+ "FilterDataset",
"ChainDataset",
]
+
def split(dataset, first_size):
"""A utility function to split a dataset into two datasets."""
first = SliceDataset(dataset, 0, first_size)
second = SliceDataset(dataset, first_size, len(dataset))
return first, second
+
class TransformDataset(Dataset):
def __init__(self, dataset, transform):
"""Dataset which is transformed from another with a transform.
@@ -141,7 +149,7 @@ class DictDataset(Dataset):
for i in six.moves.range(length)]
else:
return batches
-
+
def __len__(self):
return self._length
diff --git a/parakeet/datasets/__init__.py b/parakeet/datasets/__init__.py
index de7be70..e75da0b 100644
--- a/parakeet/datasets/__init__.py
+++ b/parakeet/datasets/__init__.py
@@ -1,2 +1,16 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from parakeet.datasets.common import *
from parakeet.datasets.ljspeech import *
\ No newline at end of file
diff --git a/parakeet/datasets/common.py b/parakeet/datasets/common.py
index e0d91a3..a1d16d6 100644
--- a/parakeet/datasets/common.py
+++ b/parakeet/datasets/common.py
@@ -1,9 +1,24 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from paddle.io import Dataset
import os
import librosa
__all__ = ["AudioFolderDataset"]
+
class AudioFolderDataset(Dataset):
def __init__(self, path, sample_rate, extension="wav"):
self.root = os.path.expanduser(path)
@@ -19,5 +34,5 @@ class AudioFolderDataset(Dataset):
def __getitem__(self, i):
file_name = self.file_names[i]
- y, _ = librosa.load(file_name, sr=self.sample_rate) # pylint: disable=unused-variable
+ y, _ = librosa.load(file_name, sr=self.sample_rate) # pylint: disable=unused-variable
return y
diff --git a/parakeet/datasets/ljspeech.py b/parakeet/datasets/ljspeech.py
index 9c2e0c3..a37863f 100644
--- a/parakeet/datasets/ljspeech.py
+++ b/parakeet/datasets/ljspeech.py
@@ -1,8 +1,23 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from paddle.io import Dataset
from pathlib import Path
__all__ = ["LJSpeechMetaData"]
+
class LJSpeechMetaData(Dataset):
def __init__(self, root):
self.root = Path(root).expanduser()
@@ -22,4 +37,3 @@ class LJSpeechMetaData(Dataset):
def __len__(self):
return len(self.records)
-
diff --git a/parakeet/frontend/__init__.py b/parakeet/frontend/__init__.py
index cee73c1..2d06dda 100644
--- a/parakeet/frontend/__init__.py
+++ b/parakeet/frontend/__init__.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from parakeet.frontend.vocab import *
from parakeet.frontend.phonectic import *
from parakeet.frontend.punctuation import *
diff --git a/parakeet/frontend/normalizer/__init__.py b/parakeet/frontend/normalizer/__init__.py
index f098650..37fd580 100644
--- a/parakeet/frontend/normalizer/__init__.py
+++ b/parakeet/frontend/normalizer/__init__.py
@@ -1,2 +1,16 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from parakeet.frontend.normalizer.normalizer import *
from parakeet.frontend.normalizer.numbers import *
diff --git a/parakeet/frontend/normalizer/abbrrviation.py b/parakeet/frontend/normalizer/abbrrviation.py
index e69de29..9118340 100644
--- a/parakeet/frontend/normalizer/abbrrviation.py
+++ b/parakeet/frontend/normalizer/abbrrviation.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
diff --git a/parakeet/frontend/normalizer/acronyms.py b/parakeet/frontend/normalizer/acronyms.py
index e69de29..9118340 100644
--- a/parakeet/frontend/normalizer/acronyms.py
+++ b/parakeet/frontend/normalizer/acronyms.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
diff --git a/parakeet/frontend/normalizer/width.py b/parakeet/frontend/normalizer/width.py
index 440557f..b1598af 100644
--- a/parakeet/frontend/normalizer/width.py
+++ b/parakeet/frontend/normalizer/width.py
@@ -1,8 +1,22 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
def full2half_width(ustr):
half = []
for u in ustr:
num = ord(u)
- if num == 0x3000: # 全角空格变半角
+ if num == 0x3000: # 全角空格变半角
num = 32
elif 0xFF01 <= num <= 0xFF5E:
num -= 0xfee0
@@ -10,15 +24,16 @@ def full2half_width(ustr):
half.append(u)
return ''.join(half)
+
def half2full_width(ustr):
full = []
for u in ustr:
num = ord(u)
- if num == 32: # 半角空格变全角
+ if num == 32: # 半角空格变全角
num = 0x3000
elif 0x21 <= num <= 0x7E:
num += 0xfee0
- u = chr(num) # to unicode
+ u = chr(num) # to unicode
full.append(u)
-
- return ''.join(full)
\ No newline at end of file
+
+ return ''.join(full)
diff --git a/parakeet/frontend/punctuation.py b/parakeet/frontend/punctuation.py
index 9984970..099e759 100644
--- a/parakeet/frontend/punctuation.py
+++ b/parakeet/frontend/punctuation.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import abc
import string
@@ -13,15 +27,8 @@ EN_PUNCT = [
"!",
]
-CN_PUNCT = [
- "、",
- ",",
- ";",
- ":",
- "。",
- "?",
- "!"
-]
+CN_PUNCT = ["、", ",", ";", ":", "。", "?", "!"]
+
def get_punctuations(lang):
if lang == "en":
@@ -30,4 +37,3 @@ def get_punctuations(lang):
return CN_PUNCT
else:
raise ValueError(f"language {lang} Not supported")
-
diff --git a/parakeet/models/transformer_tts.py b/parakeet/models/transformer_tts.py
index f84a9f8..c7f0ccd 100644
--- a/parakeet/models/transformer_tts.py
+++ b/parakeet/models/transformer_tts.py
@@ -559,7 +559,7 @@ class TransformerTTS(nn.Layer):
@classmethod
def from_pretrained(cls, frontend, config, checkpoint_path):
model = TransformerTTS(
- frontend,
+ frontend,
d_encoder=config.model.d_encoder,
d_decoder=config.model.d_decoder,
d_mel=config.data.d_mel,
@@ -575,11 +575,12 @@ class TransformerTTS(nn.Layer):
decoder_prenet_dropout=config.model.decoder_prenet_dropout,
dropout=config.model.dropout)
- iteration = checkpoint.load_parameters(model, checkpoint_path=checkpoint_path)
+ iteration = checkpoint.load_parameters(
+ model, checkpoint_path=checkpoint_path)
drop_n_heads = scheduler.StepWise(config.training.drop_n_heads)
reduction_factor = scheduler.StepWise(config.training.reduction_factor)
model.set_constants(
- reduction_factor=reduction_factor(iteration),
+ reduction_factor=reduction_factor(iteration),
drop_n_heads=drop_n_heads(iteration))
return model
diff --git a/parakeet/models/waveflow.py b/parakeet/models/waveflow.py
index d58127b..625e61f 100644
--- a/parakeet/models/waveflow.py
+++ b/parakeet/models/waveflow.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import math
import numpy as np
from typing import List, Union, Tuple
@@ -11,6 +25,7 @@ from parakeet.modules import geometry as geo
__all__ = ["WaveFlow", "ConditionalWaveFlow", "WaveFlowLoss"]
+
def fold(x, n_group):
r"""Fold audio or spectrogram's temporal dimension in to groups.
@@ -31,6 +46,7 @@ def fold(x, n_group):
new_shape = spatial_shape + [time_steps // n_group, n_group]
return paddle.reshape(x, new_shape)
+
class UpsampleNet(nn.LayerList):
"""Layer to upsample mel spectrogram to the same temporal resolution with
the corresponding waveform.
@@ -60,6 +76,7 @@ class UpsampleNet(nn.LayerList):
---------
``librosa.core.stft``
"""
+
def __init__(self, upsample_factors):
super(UpsampleNet, self).__init__()
for factor in upsample_factors:
@@ -67,16 +84,18 @@ class UpsampleNet(nn.LayerList):
init = I.Uniform(-std, std)
self.append(
nn.utils.weight_norm(
- nn.Conv2DTranspose(1, 1, (3, 2 * factor),
+ nn.Conv2DTranspose(
+ 1,
+ 1, (3, 2 * factor),
padding=(1, factor // 2),
stride=(1, factor),
weight_attr=init,
bias_attr=init)))
-
+
# upsample factors
self.upsample_factor = np.prod(upsample_factors)
self.upsample_factors = upsample_factors
-
+
def forward(self, x, trim_conv_artifact=False):
r"""Forward pass of the ``UpsampleNet``.
@@ -131,38 +150,47 @@ class ResidualBlock(nn.Layer):
dilations : int
Dilations of the Convolution2d applied to the input.
"""
+
def __init__(self, channels, cond_channels, kernel_size, dilations):
super(ResidualBlock, self).__init__()
# input conv
std = math.sqrt(1 / channels * np.prod(kernel_size))
init = I.Uniform(-std, std)
- receptive_field = [1 + (k - 1) * d for (k, d) in zip(kernel_size, dilations)]
+ receptive_field = [
+ 1 + (k - 1) * d for (k, d) in zip(kernel_size, dilations)
+ ]
rh, rw = receptive_field
- paddings = [rh - 1, 0, rw // 2, (rw - 1) // 2] # causal & same
- conv = nn.Conv2D(channels, 2 * channels, kernel_size,
- padding=paddings,
- dilation=dilations,
- weight_attr=init,
- bias_attr=init)
+ paddings = [rh - 1, 0, rw // 2, (rw - 1) // 2] # causal & same
+ conv = nn.Conv2D(
+ channels,
+ 2 * channels,
+ kernel_size,
+ padding=paddings,
+ dilation=dilations,
+ weight_attr=init,
+ bias_attr=init)
self.conv = nn.utils.weight_norm(conv)
self.rh = rh
self.rw = rw
self.dilations = dilations
-
+
# condition projection
std = math.sqrt(1 / cond_channels)
init = I.Uniform(-std, std)
- condition_proj = nn.Conv2D(cond_channels, 2 * channels, (1, 1),
- weight_attr=init, bias_attr=init)
+ condition_proj = nn.Conv2D(
+ cond_channels,
+ 2 * channels, (1, 1),
+ weight_attr=init,
+ bias_attr=init)
self.condition_proj = nn.utils.weight_norm(condition_proj)
-
+
# parametric residual & skip connection
std = math.sqrt(1 / channels)
init = I.Uniform(-std, std)
- out_proj = nn.Conv2D(channels, 2 * channels, (1, 1),
- weight_attr=init, bias_attr=init)
+ out_proj = nn.Conv2D(
+ channels, 2 * channels, (1, 1), weight_attr=init, bias_attr=init)
self.out_proj = nn.utils.weight_norm(out_proj)
-
+
def forward(self, x, condition):
"""Compute output for a whole folded sequence.
@@ -185,10 +213,10 @@ class ResidualBlock(nn.Layer):
x_in = x
x = self.conv(x)
x += self.condition_proj(condition)
-
+
content, gate = paddle.chunk(x, 2, axis=1)
x = paddle.tanh(content) * F.sigmoid(gate)
-
+
x = self.out_proj(x)
res, skip = paddle.chunk(x, 2, axis=1)
res = x_in + res
@@ -249,7 +277,7 @@ class ResidualBlock(nn.Layer):
content, gate = paddle.chunk(x_row, 2, axis=1)
x_row = paddle.tanh(content) * F.sigmoid(gate)
-
+
x_row = self.out_proj(x_row)
res, skip = paddle.chunk(x_row, 2, axis=1)
res = x_row_in + res
@@ -290,20 +318,23 @@ class ResidualNet(nn.LayerList):
ValueError
If the length of dilations_h does not equals n_layers.
"""
- def __init__(self,
- n_layer: int,
- residual_channels: int,
- condition_channels: int,
- kernel_size: Tuple[int],
+
+ def __init__(self,
+ n_layer: int,
+ residual_channels: int,
+ condition_channels: int,
+ kernel_size: Tuple[int],
dilations_h: List[int]):
if len(dilations_h) != n_layer:
- raise ValueError("number of dilations_h should equals num of layers")
+ raise ValueError(
+ "number of dilations_h should equals num of layers")
super(ResidualNet, self).__init__()
for i in range(n_layer):
- dilation = (dilations_h[i], 2 ** i)
- layer = ResidualBlock(residual_channels, condition_channels, kernel_size, dilation)
+ dilation = (dilations_h[i], 2**i)
+ layer = ResidualBlock(residual_channels, condition_channels,
+ kernel_size, dilation)
self.append(layer)
-
+
def forward(self, x, condition):
"""Comput the output of given the input and the condition.
@@ -332,7 +363,7 @@ class ResidualNet(nn.LayerList):
"""
for layer in self:
layer.start_sequence()
-
+
def add_input(self, x_row, condition_row):
"""Compute the output for a row and update the buffers.
@@ -386,33 +417,37 @@ class Flow(nn.Layer):
Number of timesteps to the folded into a group.
"""
dilations_dict = {
- 8: [1, 1, 1, 1, 1, 1, 1, 1],
- 16: [1, 1, 1, 1, 1, 1, 1, 1],
- 32: [1, 2, 4, 1, 2, 4, 1, 2],
- 64: [1, 2, 4, 8, 16, 1, 2, 4],
- 128: [1, 2, 4, 8, 16, 32, 64, 1]
+ 8: [1, 1, 1, 1, 1, 1, 1, 1],
+ 16: [1, 1, 1, 1, 1, 1, 1, 1],
+ 32: [1, 2, 4, 1, 2, 4, 1, 2],
+ 64: [1, 2, 4, 8, 16, 1, 2, 4],
+ 128: [1, 2, 4, 8, 16, 32, 64, 1]
}
-
+
def __init__(self, n_layers, channels, mel_bands, kernel_size, n_group):
super(Flow, self).__init__()
# input projection
self.input_proj = nn.utils.weight_norm(
- nn.Conv2D(1, channels, (1, 1),
- weight_attr=I.Uniform(-1., 1.),
- bias_attr=I.Uniform(-1., 1.)))
-
+ nn.Conv2D(
+ 1,
+ channels, (1, 1),
+ weight_attr=I.Uniform(-1., 1.),
+ bias_attr=I.Uniform(-1., 1.)))
+
# residual net
- self.resnet = ResidualNet(n_layers, channels, mel_bands, kernel_size,
+ self.resnet = ResidualNet(n_layers, channels, mel_bands, kernel_size,
self.dilations_dict[n_group])
-
+
# output projection
- self.output_proj = nn.Conv2D(channels, 2, (1, 1),
- weight_attr=I.Constant(0.),
- bias_attr=I.Constant(0.))
-
+ self.output_proj = nn.Conv2D(
+ channels,
+ 2, (1, 1),
+ weight_attr=I.Constant(0.),
+ bias_attr=I.Constant(0.))
+
# specs
self.n_group = n_group
-
+
def _predict_parameters(self, x, condition):
x = self.input_proj(x)
x = self.resnet(x, condition)
@@ -421,11 +456,11 @@ class Flow(nn.Layer):
return logs, b
def _transform(self, x, logs, b):
- z_0 = x[:, :, :1, :] # the first row, just copy it
- z_out = x[:, :, 1:, :] * paddle.exp(logs) + b
+ z_0 = x[:, :, :1, :] # the first row, just copy it
+ z_out = x[:, :, 1:, :] * paddle.exp(logs) + b
z_out = paddle.concat([z_0, z_out], axis=2)
return z_out
-
+
def forward(self, x, condition):
"""Probability density estimation. It is done by inversely transform
a sample from p(X) into a sample from p(Z).
@@ -452,8 +487,8 @@ class Flow(nn.Layer):
transformation from x to z.
"""
# (B, C, H-1, W)
- logs, b = self._predict_parameters(
- x[:, :, :-1, :], condition[:, :, 1:, :])
+ logs, b = self._predict_parameters(x[:, :, :-1, :],
+ condition[:, :, 1:, :])
z = self._transform(x, logs, b)
return z, (logs, b)
@@ -467,7 +502,7 @@ class Flow(nn.Layer):
def _inverse_transform_row(self, z_row, logs, b):
x_row = (z_row - b) * paddle.exp(-logs)
return x_row
-
+
def _inverse_row(self, z_row, x_row, condition_row):
logs, b = self._predict_row_parameters(x_row, condition_row)
x_next_row = self._inverse_transform_row(z_row, logs, b)
@@ -475,7 +510,7 @@ class Flow(nn.Layer):
def _start_sequence(self):
self.resnet.start_sequence()
-
+
def inverse(self, z, condition):
"""Sampling from the the distrition p(X). It is done by sample form
p(Z) and transform the sample. It is a auto regressive transformation.
@@ -510,15 +545,16 @@ class Flow(nn.Layer):
self._start_sequence()
for i in range(1, self.n_group):
- x_row = x[-1] # actuallt i-1:i
- z_row = z[:, :, i:i+1, :]
- condition_row = condition[:, :, i:i+1, :]
+ x_row = x[-1] # actuallt i-1:i
+ z_row = z[:, :, i:i + 1, :]
+ condition_row = condition[:, :, i:i + 1, :]
- x_next_row, (logs, b) = self._inverse_row(z_row, x_row, condition_row)
+ x_next_row, (logs, b) = self._inverse_row(z_row, x_row,
+ condition_row)
x.append(x_next_row)
logs_list.append(logs)
b_list.append(b)
-
+
x = paddle.concat(x, 2)
logs = paddle.concat(logs_list, 2)
b = paddle.concat(b_list, 2)
@@ -549,21 +585,25 @@ class WaveFlow(nn.LayerList):
kernel_size : Union[int, List[int]]
Kernel size of the convolution layer in each ResidualBlock.
"""
- def __init__(self, n_flows, n_layers, n_group, channels, mel_bands, kernel_size):
+
+ def __init__(self, n_flows, n_layers, n_group, channels, mel_bands,
+ kernel_size):
if n_group % 2 or n_flows % 2:
- raise ValueError("number of flows and number of group must be even "
- "since a permutation along group among flows is used.")
+ raise ValueError(
+ "number of flows and number of group must be even "
+ "since a permutation along group among flows is used.")
super(WaveFlow, self).__init__()
for _ in range(n_flows):
- self.append(Flow(n_layers, channels, mel_bands, kernel_size, n_group))
-
+ self.append(
+ Flow(n_layers, channels, mel_bands, kernel_size, n_group))
+
# permutations in h
self.perms = self._create_perm(n_group, n_flows)
# specs
self.n_group = n_group
self.n_flows = n_flows
-
+
def _create_perm(self, n_group, n_flows):
indices = list(range(n_group))
half = n_group // 2
@@ -572,20 +612,21 @@ class WaveFlow(nn.LayerList):
if i < n_flows // 2:
perms.append(indices[::-1])
else:
- perm = list(reversed(indices[:half])) + list(reversed(indices[half:]))
+ perm = list(reversed(indices[:half])) + list(
+ reversed(indices[half:]))
perms.append(perm)
return perms
-
+
def _trim(self, x, condition):
assert condition.shape[-1] >= x.shape[-1]
pruned_len = int(x.shape[-1] // self.n_group * self.n_group)
-
+
if x.shape[-1] > pruned_len:
x = x[:, :pruned_len]
if condition.shape[-1] > pruned_len:
condition = condition[:, :, :pruned_len]
return x, condition
-
+
def forward(self, x, condition):
"""Probability density estimation of random variable x given the
condition.
@@ -610,21 +651,23 @@ class WaveFlow(nn.LayerList):
# x: (B, T)
# condition: (B, C, T) upsampled condition
x, condition = self._trim(x, condition)
-
+
# to (B, C, h, T//h) layout
- x = paddle.unsqueeze(paddle.transpose(fold(x, self.n_group), [0, 2, 1]), 1)
- condition = paddle.transpose(fold(condition, self.n_group), [0, 1, 3, 2])
-
+ x = paddle.unsqueeze(
+ paddle.transpose(fold(x, self.n_group), [0, 2, 1]), 1)
+ condition = paddle.transpose(
+ fold(condition, self.n_group), [0, 1, 3, 2])
+
# flows
logs_list = []
for i, layer in enumerate(self):
- x, (logs, b) = layer(x, condition)
+ x, (logs, b) = layer(x, condition)
logs_list.append(logs)
# permute paddle has no shuffle dim
x = geo.shuffle_dim(x, 2, perm=self.perms[i])
condition = geo.shuffle_dim(condition, 2, perm=self.perms[i])
- z = paddle.squeeze(x, 1) # (B, H, W)
+ z = paddle.squeeze(x, 1) # (B, H, W)
batch_size = z.shape[0]
z = paddle.reshape(paddle.transpose(z, [0, 2, 1]), [batch_size, -1])
@@ -654,8 +697,10 @@ class WaveFlow(nn.LayerList):
z, condition = self._trim(z, condition)
# to (B, C, h, T//h) layout
- z = paddle.unsqueeze(paddle.transpose(fold(z, self.n_group), [0, 2, 1]), 1)
- condition = paddle.transpose(fold(condition, self.n_group), [0, 1, 3, 2])
+ z = paddle.unsqueeze(
+ paddle.transpose(fold(z, self.n_group), [0, 2, 1]), 1)
+ condition = paddle.transpose(
+ fold(condition, self.n_group), [0, 1, 3, 2])
# reverse it flow by flow
for i in reversed(range(self.n_flows)):
@@ -663,7 +708,7 @@ class WaveFlow(nn.LayerList):
condition = geo.shuffle_dim(condition, 2, perm=self.perms[i])
z, (logs, b) = self[i].inverse(z, condition)
- x = paddle.squeeze(z, 1) # (B, H, W)
+ x = paddle.squeeze(z, 1) # (B, H, W)
batch_size = x.shape[0]
x = paddle.reshape(paddle.transpose(x, [0, 2, 1]), [batch_size, -1])
return x
@@ -695,23 +740,24 @@ class ConditionalWaveFlow(nn.LayerList):
kernel_size : Union[int, List[int]]
Kernel size of the convolution layer in each ResidualBlock.
"""
- def __init__(self,
- upsample_factors: List[int],
- n_flows: int,
- n_layers: int,
- n_group: int,
- channels: int,
- n_mels: int,
- kernel_size: Union[int, List[int]]):
+
+ def __init__(self,
+ upsample_factors: List[int],
+ n_flows: int,
+ n_layers: int,
+ n_group: int,
+ channels: int,
+ n_mels: int,
+ kernel_size: Union[int, List[int]]):
super(ConditionalWaveFlow, self).__init__()
self.encoder = UpsampleNet(upsample_factors)
self.decoder = WaveFlow(
- n_flows=n_flows,
- n_layers=n_layers,
- n_group=n_group,
- channels=channels,
- mel_bands=n_mels,
- kernel_size=kernel_size)
+ n_flows=n_flows,
+ n_layers=n_layers,
+ n_group=n_group,
+ channels=channels,
+ mel_bands=n_mels,
+ kernel_size=kernel_size)
def forward(self, audio, mel):
"""Compute the transformed random variable z (x to z) and the log of
@@ -737,7 +783,7 @@ class ConditionalWaveFlow(nn.LayerList):
condition = self.encoder(mel)
z, log_det_jacobian = self.decoder(audio, condition)
return z, log_det_jacobian
-
+
@paddle.no_grad()
def infer(self, mel):
r"""Generate raw audio given mel spectrogram.
@@ -752,12 +798,12 @@ class ConditionalWaveFlow(nn.LayerList):
Tensor : [shape=(B, T)]
The synthesized audio, where``T <= T_mel \* upsample_factors``.
"""
- condition = self.encoder(mel, trim_conv_artifact=True) #(B, C, T)
+ condition = self.encoder(mel, trim_conv_artifact=True) #(B, C, T)
batch_size, _, time_steps = condition.shape
z = paddle.randn([batch_size, time_steps], dtype=mel.dtype)
x = self.decoder.inverse(z, condition)
return x
-
+
@paddle.no_grad()
def predict(self, mel):
"""Generate raw audio given mel spectrogram.
@@ -777,7 +823,7 @@ class ConditionalWaveFlow(nn.LayerList):
audio = self.infer(mel)
audio = audio[0].numpy()
return audio
-
+
@classmethod
def from_pretrained(cls, config, checkpoint_path):
"""Build a ConditionalWaveFlow model from a pretrained model.
@@ -795,14 +841,13 @@ class ConditionalWaveFlow(nn.LayerList):
ConditionalWaveFlow
The model built from pretrained result.
"""
- model = cls(
- upsample_factors=config.model.upsample_factors,
- n_flows=config.model.n_flows,
- n_layers=config.model.n_layers,
- n_group=config.model.n_group,
- channels=config.model.channels,
- n_mels=config.data.n_mels,
- kernel_size=config.model.kernel_size)
+ model = cls(upsample_factors=config.model.upsample_factors,
+ n_flows=config.model.n_flows,
+ n_layers=config.model.n_layers,
+ n_group=config.model.n_group,
+ channels=config.model.channels,
+ n_mels=config.data.n_mels,
+ kernel_size=config.model.kernel_size)
checkpoint.load_parameters(model, checkpoint_path=checkpoint_path)
return model
@@ -816,6 +861,7 @@ class WaveFlowLoss(nn.Layer):
The standard deviation of the gaussian noise used in WaveFlow, by
default 1.0.
"""
+
def __init__(self, sigma=1.0):
super(WaveFlowLoss, self).__init__()
self.sigma = sigma
@@ -839,6 +885,7 @@ class WaveFlowLoss(nn.Layer):
Tensor [shape=(1,)]
The loss.
"""
- loss = paddle.sum(z * z) / (2 * self.sigma * self.sigma) - log_det_jacobian
+ loss = paddle.sum(z * z) / (2 * self.sigma * self.sigma
+ ) - log_det_jacobian
loss = loss / np.prod(z.shape)
return loss + self.const
diff --git a/parakeet/models/wavenet.py b/parakeet/models/wavenet.py
index 8e6f272..5ff3435 100644
--- a/parakeet/models/wavenet.py
+++ b/parakeet/models/wavenet.py
@@ -18,7 +18,7 @@ from typing import Union, Sequence, List
from tqdm import trange
import numpy as np
-import paddle
+import paddle
from paddle import nn
from paddle.nn import functional as F
import paddle.fluid.initializer as I
@@ -30,6 +30,7 @@ from parakeet.utils import checkpoint, layer_tools
__all__ = ["WaveNet", "ConditionalWaveNet"]
+
def crop(x, audio_start, audio_length):
"""Crop the upsampled condition to match audio_length.
@@ -96,6 +97,7 @@ class UpsampleNet(nn.LayerList):
---------
``librosa.core.stft``
"""
+
def __init__(self, upscale_factors=[16, 16]):
super(UpsampleNet, self).__init__()
self.upscale_factors = list(upscale_factors)
@@ -106,9 +108,11 @@ class UpsampleNet(nn.LayerList):
for factor in self.upscale_factors:
self.append(
nn.utils.weight_norm(
- nn.Conv2DTranspose(1, 1,
- kernel_size=(3, 2 * factor),
- stride=(1, factor),
+ nn.Conv2DTranspose(
+ 1,
+ 1,
+ kernel_size=(3, 2 * factor),
+ stride=(1, factor),
padding=(1, factor // 2))))
def forward(self, x):
@@ -159,29 +163,34 @@ class ResidualBlock(nn.Layer):
dilation :int
Dilation of the internal convolution cells.
"""
- def __init__(self,
- residual_channels: int,
- condition_dim: int,
+
+ def __init__(self,
+ residual_channels: int,
+ condition_dim: int,
filter_size: Union[int, Sequence[int]],
dilation: int):
-
+
super(ResidualBlock, self).__init__()
dilated_channels = 2 * residual_channels
# following clarinet's implementation, we do not have parametric residual
# & skip connection.
- _filter_size = filter_size[0] if isinstance(filter_size, (list, tuple)) else filter_size
+ _filter_size = filter_size[0] if isinstance(filter_size, (
+ list, tuple)) else filter_size
std = math.sqrt(1 / (_filter_size * residual_channels))
- conv = Conv1dCell(residual_channels,
- dilated_channels,
- filter_size,
- dilation=dilation,
- weight_attr=I.Normal(scale=std))
+ conv = Conv1dCell(
+ residual_channels,
+ dilated_channels,
+ filter_size,
+ dilation=dilation,
+ weight_attr=I.Normal(scale=std))
self.conv = nn.utils.weight_norm(conv)
std = math.sqrt(1 / condition_dim)
- condition_proj = Conv1dCell(condition_dim, dilated_channels, (1,),
- weight_attr=I.Normal(scale=std))
+ condition_proj = Conv1dCell(
+ condition_dim,
+ dilated_channels, (1, ),
+ weight_attr=I.Normal(scale=std))
self.condition_proj = nn.utils.weight_norm(condition_proj)
self.filter_size = filter_size
@@ -309,10 +318,11 @@ class ResidualNet(nn.LayerList):
Kernel size of the internal ``Conv1dCell`` of each ``ResidualBlock``.
"""
- def __init__(self,
- n_stack: int,
- n_loop: int,
- residual_channels: int,
+
+ def __init__(self,
+ n_stack: int,
+ n_loop: int,
+ residual_channels: int,
condition_dim: int,
filter_size: int):
super(ResidualNet, self).__init__()
@@ -320,7 +330,9 @@ class ResidualNet(nn.LayerList):
dilations = [2**i for i in range(n_loop)] * n_stack
self.context_size = 1 + sum(dilations)
for dilation in dilations:
- self.append(ResidualBlock(residual_channels, condition_dim, filter_size, dilation))
+ self.append(
+ ResidualBlock(residual_channels, condition_dim, filter_size,
+ dilation))
def forward(self, x, condition=None):
"""Forward pass of ``ResidualNet``.
@@ -345,7 +357,7 @@ class ResidualNet(nn.LayerList):
skip_connections = skip
else:
skip_connections = paddle.scale(skip_connections + skip,
- math.sqrt(0.5))
+ math.sqrt(0.5))
return skip_connections
def start_sequence(self):
@@ -381,7 +393,7 @@ class ResidualNet(nn.LayerList):
skip_connections = skip
else:
skip_connections = paddle.scale(skip_connections + skip,
- math.sqrt(0.5))
+ math.sqrt(0.5))
return skip_connections
@@ -426,6 +438,7 @@ class WaveNet(nn.Layer):
This is only used for computing loss when ``loss_type`` is "mog", If
the predicted log scale is less than -9.0, it is clipped at -9.0.
"""
+
def __init__(self, n_stack, n_loop, residual_channels, output_dim,
condition_dim, filter_size, loss_type, log_scale_min):
@@ -437,19 +450,24 @@ class WaveNet(nn.Layer):
else:
if (output_dim % 3 != 0):
raise ValueError(
- "with Mixture of Gaussians(mog) output, the output dim must be divisible by 3, but get {}".format(output_dim))
- self.embed = nn.utils.weight_norm(nn.Linear(1, residual_channels), dim=1)
+ "with Mixture of Gaussians(mog) output, the output dim must be divisible by 3, but get {}".
+ format(output_dim))
+ self.embed = nn.utils.weight_norm(
+ nn.Linear(1, residual_channels), dim=1)
self.resnet = ResidualNet(n_stack, n_loop, residual_channels,
condition_dim, filter_size)
self.context_size = self.resnet.context_size
skip_channels = residual_channels # assume the same channel
- self.proj1 = nn.utils.weight_norm(nn.Linear(skip_channels, skip_channels), dim=1)
- self.proj2 = nn.utils.weight_norm(nn.Linear(skip_channels, skip_channels), dim=1)
+ self.proj1 = nn.utils.weight_norm(
+ nn.Linear(skip_channels, skip_channels), dim=1)
+ self.proj2 = nn.utils.weight_norm(
+ nn.Linear(skip_channels, skip_channels), dim=1)
# if loss_type is softmax, output_dim is n_vocab of waveform magnitude.
# if loss_type is mog, output_dim is 3 * gaussian, (weight, mean and stddev)
- self.proj3 = nn.utils.weight_norm(nn.Linear(skip_channels, output_dim), dim=1)
+ self.proj3 = nn.utils.weight_norm(
+ nn.Linear(skip_channels, output_dim), dim=1)
self.loss_type = loss_type
self.output_dim = output_dim
@@ -781,26 +799,28 @@ class ConditionalWaveNet(nn.Layer):
This is only used for computing loss when ``loss_type`` is "mog", If
the predicted log scale is less than -9.0, it is clipped at -9.0.
"""
- def __init__(self,
- upsample_factors: List[int],
- n_stack: int,
- n_loop: int,
- residual_channels: int,
+
+ def __init__(self,
+ upsample_factors: List[int],
+ n_stack: int,
+ n_loop: int,
+ residual_channels: int,
output_dim: int,
- n_mels: int,
- filter_size: int=2,
- loss_type: str="mog",
+ n_mels: int,
+ filter_size: int=2,
+ loss_type: str="mog",
log_scale_min: float=-9.0):
super(ConditionalWaveNet, self).__init__()
self.encoder = UpsampleNet(upsample_factors)
- self.decoder = WaveNet(n_stack=n_stack,
- n_loop=n_loop,
- residual_channels=residual_channels,
- output_dim=output_dim,
- condition_dim=n_mels,
- filter_size=filter_size,
- loss_type=loss_type,
- log_scale_min=log_scale_min)
+ self.decoder = WaveNet(
+ n_stack=n_stack,
+ n_loop=n_loop,
+ residual_channels=residual_channels,
+ output_dim=output_dim,
+ condition_dim=n_mels,
+ filter_size=filter_size,
+ loss_type=loss_type,
+ log_scale_min=log_scale_min)
def forward(self, audio, mel, audio_start):
"""Compute the output distribution given the mel spectrogram and the input(for teacher force training).
@@ -895,11 +915,11 @@ class ConditionalWaveNet(nn.Layer):
self.decoder.start_sequence()
x_t = paddle.zeros((batch_size, ), dtype=mel.dtype)
for i in trange(time_steps):
- c_t = condition[:, :, i] # (B, C)
- y_t = self.decoder.add_input(x_t, c_t) #(B, C)
+ c_t = condition[:, :, i] # (B, C)
+ y_t = self.decoder.add_input(x_t, c_t) #(B, C)
y_t = paddle.unsqueeze(y_t, 1)
- x_t = self.sample(y_t) # (B, 1)
- x_t = paddle.squeeze(x_t, 1) #(B,)
+ x_t = self.sample(y_t) # (B, 1)
+ x_t = paddle.squeeze(x_t, 1) #(B,)
samples.append(x_t)
samples = paddle.stack(samples, -1)
return samples
@@ -943,16 +963,15 @@ class ConditionalWaveNet(nn.Layer):
ConditionalWaveNet
The model built from pretrained result.
"""
- model = cls(
- upsample_factors=config.model.upsample_factors,
- n_stack=config.model.n_stack,
- n_loop=config.model.n_loop,
- residual_channels=config.model.residual_channels,
- output_dim=config.model.output_dim,
- n_mels=config.data.n_mels,
- filter_size=config.model.filter_size,
- loss_type=config.model.loss_type,
- log_scale_min=config.model.log_scale_min)
+ model = cls(upsample_factors=config.model.upsample_factors,
+ n_stack=config.model.n_stack,
+ n_loop=config.model.n_loop,
+ residual_channels=config.model.residual_channels,
+ output_dim=config.model.output_dim,
+ n_mels=config.data.n_mels,
+ filter_size=config.model.filter_size,
+ loss_type=config.model.loss_type,
+ log_scale_min=config.model.log_scale_min)
layer_tools.summary(model)
checkpoint.load_parameters(model, checkpoint_path=checkpoint_path)
return model
diff --git a/parakeet/modules/audio.py b/parakeet/modules/audio.py
index ebcc6c6..03e42b0 100644
--- a/parakeet/modules/audio.py
+++ b/parakeet/modules/audio.py
@@ -1,8 +1,22 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import paddle
from paddle import nn
from paddle.nn import functional as F
from scipy import signal
-import numpy as np
+import numpy as np
__all__ = ["quantize", "dequantize", "STFT"]
@@ -86,6 +100,7 @@ class STFT(nn.Layer):
Ony ``center`` and ``reflect`` padding is supported now.
"""
+
def __init__(self, n_fft, hop_length, win_length, window="hanning"):
super(STFT, self).__init__()
self.hop_length = hop_length
@@ -109,7 +124,8 @@ class STFT(nn.Layer):
(self.n_bin, 1, 1, self.n_fft))
w = np.concatenate([w_real, w_imag], axis=0)
- self.weight = paddle.cast(paddle.to_tensor(w), paddle.get_default_dtype())
+ self.weight = paddle.cast(
+ paddle.to_tensor(w), paddle.get_default_dtype())
def forward(self, x):
"""Compute the stft transform.
diff --git a/parakeet/modules/conv.py b/parakeet/modules/conv.py
index b57abf2..d984605 100644
--- a/parakeet/modules/conv.py
+++ b/parakeet/modules/conv.py
@@ -20,6 +20,7 @@ __all__ = [
"Conv1dBatchNorm",
]
+
class Conv1dCell(nn.Conv1D):
"""A subclass of Conv1D layer, which can be used in an autoregressive
decoder like an RNN cell.
@@ -231,6 +232,7 @@ class Conv1dBatchNorm(nn.Layer):
epsilon : [type], optional
The epsilon of the BatchNorm1D layer, by default 1e-05
"""
+
def __init__(self,
in_channels,
out_channels,
diff --git a/parakeet/modules/geometry.py b/parakeet/modules/geometry.py
index ec96daf..05a5931 100644
--- a/parakeet/modules/geometry.py
+++ b/parakeet/modules/geometry.py
@@ -1,6 +1,21 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import numpy as np
import paddle
+
def shuffle_dim(x, axis, perm=None):
"""Permute input tensor along aixs given the permutation or randomly.
@@ -32,7 +47,7 @@ def shuffle_dim(x, axis, perm=None):
perm = np.array(perm)
else:
perm = np.random.permutation(size)
-
+
perm = paddle.to_tensor(perm)
out = paddle.gather(x, perm, axis)
return out
diff --git a/parakeet/modules/losses.py b/parakeet/modules/losses.py
index 3e22480..ab188fd 100644
--- a/parakeet/modules/losses.py
+++ b/parakeet/modules/losses.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import numba
import numpy as np
import paddle
@@ -5,12 +19,13 @@ from paddle import nn
from paddle.nn import functional as F
__all__ = [
- "weighted_mean",
- "masked_l1_loss",
- "masked_softmax_with_cross_entropy",
+ "weighted_mean",
+ "masked_l1_loss",
+ "masked_softmax_with_cross_entropy",
"diagonal_loss",
]
+
def weighted_mean(input, weight):
"""Weighted mean. It can also be used as masked mean.
@@ -88,12 +103,11 @@ def masked_softmax_with_cross_entropy(logits, label, mask, axis=-1):
return loss
-def diagonal_loss(
- attentions,
- input_lengths,
- target_lengths,
- g=0.2,
- multihead=False):
+def diagonal_loss(attentions,
+ input_lengths,
+ target_lengths,
+ g=0.2,
+ multihead=False):
"""A metric to evaluate how diagonal a attention distribution is.
It is computed for batch attention distributions. For each attention
@@ -133,6 +147,7 @@ def diagonal_loss(
else:
return paddle.mean(attentions * paddle.unsqueeze(W_tensor, 1))
+
@numba.jit(nopython=True)
def guided_attention(N, max_N, T, max_T, g):
W = np.zeros((max_T, max_N), dtype=np.float32)
@@ -142,6 +157,7 @@ def guided_attention(N, max_N, T, max_T, g):
# (T_dec, T_enc)
return W
+
def guided_attentions(input_lengths, target_lengths, g=0.2):
B = len(input_lengths)
max_input_len = input_lengths.max()
@@ -151,4 +167,4 @@ def guided_attentions(input_lengths, target_lengths, g=0.2):
W[b] = guided_attention(input_lengths[b], max_input_len,
target_lengths[b], max_target_len, g)
# (B, T_dec, T_enc)
- return W
\ No newline at end of file
+ return W
diff --git a/parakeet/modules/masking.py b/parakeet/modules/masking.py
index c54a5b1..96871a9 100644
--- a/parakeet/modules/masking.py
+++ b/parakeet/modules/masking.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import paddle
from paddle.fluid.layers import sequence_mask
@@ -8,6 +22,7 @@ __all__ = [
"future_mask",
]
+
def id_mask(input, padding_index=0, dtype="bool"):
"""Generate mask with input ids.
diff --git a/parakeet/modules/positional_encoding.py b/parakeet/modules/positional_encoding.py
index 084ccf3..07a86c9 100644
--- a/parakeet/modules/positional_encoding.py
+++ b/parakeet/modules/positional_encoding.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import math
import numpy as np
import paddle
@@ -5,6 +19,7 @@ from paddle.nn import functional as F
__all__ = ["positional_encoding"]
+
def positional_encoding(start_index, length, size, dtype=None):
r"""Generate standard positional encoding matrix.
@@ -37,7 +52,7 @@ def positional_encoding(start_index, length, size, dtype=None):
dtype = dtype or paddle.get_default_dtype()
channel = np.arange(0, size, 2)
index = np.arange(start_index, start_index + length, 1)
- p = np.expand_dims(index, -1) / (10000 ** (channel / float(size)))
+ p = np.expand_dims(index, -1) / (10000**(channel / float(size)))
encodings = np.zeros([length, size])
encodings[:, 0::2] = np.sin(p)
encodings[:, 1::2] = np.cos(p)
diff --git a/parakeet/modules/transformer.py b/parakeet/modules/transformer.py
index 18a7523..e857990 100644
--- a/parakeet/modules/transformer.py
+++ b/parakeet/modules/transformer.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import math
import paddle
from paddle import nn
@@ -12,6 +26,7 @@ __all__ = [
"TransformerDecoderLayer",
]
+
class PositionwiseFFN(nn.Layer):
"""A faithful implementation of Position-wise Feed-Forward Network
in `Attention is All You Need `_.
@@ -30,10 +45,8 @@ class PositionwiseFFN(nn.Layer):
The probability of the Dropout applied to the output of the first
layer, by default 0.
"""
- def __init__(self,
- input_size: int,
- hidden_size: int,
- dropout=0.0):
+
+ def __init__(self, input_size: int, hidden_size: int, dropout=0.0):
super(PositionwiseFFN, self).__init__()
self.linear1 = nn.Linear(input_size, hidden_size)
self.linear2 = nn.Linear(hidden_size, input_size)
@@ -86,16 +99,17 @@ class TransformerEncoderLayer(nn.Layer):
------
It uses the PostLN (post layer norm) scheme.
"""
+
def __init__(self, d_model, n_heads, d_ffn, dropout=0.):
super(TransformerEncoderLayer, self).__init__()
self.self_mha = attn.MultiheadAttention(d_model, n_heads, dropout)
self.layer_norm1 = nn.LayerNorm([d_model], epsilon=1e-6)
-
+
self.ffn = PositionwiseFFN(d_model, d_ffn, dropout)
self.layer_norm2 = nn.LayerNorm([d_model], epsilon=1e-6)
-
+
self.dropout = dropout
-
+
def forward(self, x, mask):
"""Forward pass of TransformerEncoderLayer.
@@ -118,14 +132,12 @@ class TransformerEncoderLayer(nn.Layer):
"""
context_vector, attn_weights = self.self_mha(x, x, x, mask)
x = self.layer_norm1(
- F.dropout(x + context_vector,
- self.dropout,
- training=self.training))
-
+ F.dropout(
+ x + context_vector, self.dropout, training=self.training))
+
x = self.layer_norm2(
- F.dropout(x + self.ffn(x),
- self.dropout,
- training=self.training))
+ F.dropout(
+ x + self.ffn(x), self.dropout, training=self.training))
return x, attn_weights
@@ -155,19 +167,20 @@ class TransformerDecoderLayer(nn.Layer):
------
It uses the PostLN (post layer norm) scheme.
"""
+
def __init__(self, d_model, n_heads, d_ffn, dropout=0.):
super(TransformerDecoderLayer, self).__init__()
self.self_mha = attn.MultiheadAttention(d_model, n_heads, dropout)
self.layer_norm1 = nn.LayerNorm([d_model], epsilon=1e-6)
-
+
self.cross_mha = attn.MultiheadAttention(d_model, n_heads, dropout)
self.layer_norm2 = nn.LayerNorm([d_model], epsilon=1e-6)
-
+
self.ffn = PositionwiseFFN(d_model, d_ffn, dropout)
self.layer_norm3 = nn.LayerNorm([d_model], epsilon=1e-6)
-
+
self.dropout = dropout
-
+
def forward(self, q, k, v, encoder_mask, decoder_mask):
"""Forward pass of TransformerEncoderLayer.
@@ -197,20 +210,19 @@ class TransformerDecoderLayer(nn.Layer):
cross_attn_weights : Tensor [shape=(batch_size, n_heads, time_steps_q, time_steps_k)]
Decoder-encoder cross attention.
"""
- context_vector, self_attn_weights = self.self_mha(q, q, q, decoder_mask)
+ context_vector, self_attn_weights = self.self_mha(q, q, q,
+ decoder_mask)
q = self.layer_norm1(
- F.dropout(q + context_vector,
- self.dropout,
- training=self.training))
-
- context_vector, cross_attn_weights = self.cross_mha(q, k, v, encoder_mask)
+ F.dropout(
+ q + context_vector, self.dropout, training=self.training))
+
+ context_vector, cross_attn_weights = self.cross_mha(q, k, v,
+ encoder_mask)
q = self.layer_norm2(
- F.dropout(q + context_vector,
- self.dropout,
- training=self.training))
-
+ F.dropout(
+ q + context_vector, self.dropout, training=self.training))
+
q = self.layer_norm3(
- F.dropout(q + self.ffn(q),
- self.dropout,
- training=self.training))
+ F.dropout(
+ q + self.ffn(q), self.dropout, training=self.training))
return q, self_attn_weights, cross_attn_weights
diff --git a/parakeet/training/__init__.py b/parakeet/training/__init__.py
index cb1c59b..aec401c 100644
--- a/parakeet/training/__init__.py
+++ b/parakeet/training/__init__.py
@@ -1,2 +1,16 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from parakeet.training.cli import *
from parakeet.training.experiment import *
diff --git a/parakeet/training/cli.py b/parakeet/training/cli.py
index e6b6fe5..a3cfbda 100644
--- a/parakeet/training/cli.py
+++ b/parakeet/training/cli.py
@@ -1,5 +1,20 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import argparse
+
def default_argument_parser():
r"""A simple yet genral argument parser for experiments with parakeet.
@@ -46,5 +61,5 @@ def default_argument_parser():
# overwrite extra config and default config
parser.add_argument("--opts", nargs=argparse.REMAINDER, help="options to overwrite --config file and the default config, passing in KEY VALUE pairs")
# yapd: enable
-
+
return parser
diff --git a/parakeet/training/default_config.py b/parakeet/training/default_config.py
index f4b9c29..583f6e6 100644
--- a/parakeet/training/default_config.py
+++ b/parakeet/training/default_config.py
@@ -1,12 +1,26 @@
-from yacs.config import CfgNode
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from yacs.config import CfgNode
_C = CfgNode(
dict(
- valid_interval=1000, # validation
- save_interval=10000, # checkpoint
- max_iteration=900000, # max iteration to train
- )
-)
+ valid_interval=1000, # validation
+ save_interval=10000, # checkpoint
+ max_iteration=900000, # max iteration to train
+ ))
+
def get_default_training_config():
return _C.clone()
diff --git a/parakeet/training/experiment.py b/parakeet/training/experiment.py
index 1bf0af6..16da93d 100644
--- a/parakeet/training/experiment.py
+++ b/parakeet/training/experiment.py
@@ -27,6 +27,7 @@ from parakeet.utils import checkpoint, mp_tools
__all__ = ["ExperimentBase"]
+
class ExperimentBase(object):
"""
An experiment template in order to structure the training code and take
diff --git a/parakeet/utils/checkpoint.py b/parakeet/utils/checkpoint.py
index ec6f282..0d2a2e2 100644
--- a/parakeet/utils/checkpoint.py
+++ b/parakeet/utils/checkpoint.py
@@ -45,6 +45,7 @@ def _load_latest_checkpoint(checkpoint_dir: str) -> int:
return iteration
+
def _save_checkpoint(checkpoint_dir: str, iteration: int):
"""Save the iteration number of the latest model to be checkpointed.
@@ -60,6 +61,7 @@ def _save_checkpoint(checkpoint_dir: str, iteration: int):
with open(checkpoint_record, "wt") as handle:
handle.write("model_checkpoint_path: step-{}".format(iteration))
+
def load_parameters(model,
optimizer=None,
checkpoint_dir=None,
@@ -97,18 +99,19 @@ def load_parameters(model,
params_path = checkpoint_path + ".pdparams"
model_dict = paddle.load(params_path)
model.set_state_dict(model_dict)
- print("[checkpoint] Rank {}: loaded model from {}".format(
- local_rank, params_path))
-
+ print("[checkpoint] Rank {}: loaded model from {}".format(local_rank,
+ params_path))
+
optimizer_path = checkpoint_path + ".pdopt"
if optimizer and os.path.isfile(optimizer_path):
optimizer_dict = paddle.load(optimizer_path)
optimizer.set_state_dict(optimizer_dict)
- print("[checkpoint] Rank {}: loaded optimizer state from {}".
- format(local_rank, optimizer_path))
+ print("[checkpoint] Rank {}: loaded optimizer state from {}".format(
+ local_rank, optimizer_path))
return iteration
+
@mp_tools.rank_zero_only
def save_parameters(checkpoint_dir, iteration, model, optimizer=None):
"""Checkpoint the latest trained model parameters.
@@ -124,7 +127,7 @@ def save_parameters(checkpoint_dir, iteration, model, optimizer=None):
None
"""
checkpoint_path = os.path.join(checkpoint_dir, "step-{}".format(iteration))
-
+
model_dict = model.state_dict()
params_path = checkpoint_path + ".pdparams"
paddle.save(model_dict, params_path)
diff --git a/parakeet/utils/internals.py b/parakeet/utils/internals.py
index c72a9b0..968a604 100644
--- a/parakeet/utils/internals.py
+++ b/parakeet/utils/internals.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import numpy as np
from paddle.framework import core
diff --git a/parakeet/utils/layer_tools.py b/parakeet/utils/layer_tools.py
index 2268377..fcda44f 100644
--- a/parakeet/utils/layer_tools.py
+++ b/parakeet/utils/layer_tools.py
@@ -28,6 +28,7 @@ def summary(layer: nn.Layer):
print("layer has {} parameters, {} elements.".format(num_params,
num_elements))
+
def gradient_norm(layer: nn.Layer):
grad_norm_dict = {}
for name, param in layer.state_dict().items():
@@ -36,6 +37,7 @@ def gradient_norm(layer: nn.Layer):
grad_norm_dict[name] = np.linalg.norm(grad) / grad.size
return grad_norm_dict
+
def recursively_remove_weight_norm(layer: nn.Layer):
for layer in layer.sublayers():
try:
@@ -44,10 +46,12 @@ def recursively_remove_weight_norm(layer: nn.Layer):
# ther is not weight norm hoom in this layer
pass
+
def freeze(layer: nn.Layer):
for param in layer.parameters():
param.trainable = False
+
def unfreeze(layer: nn.Layer):
for param in layer.parameters():
param.trainable = True
diff --git a/parakeet/utils/mp_tools.py b/parakeet/utils/mp_tools.py
index 0b9c6dc..a4bc97a 100644
--- a/parakeet/utils/mp_tools.py
+++ b/parakeet/utils/mp_tools.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import paddle
from paddle import distributed as dist
from functools import wraps
@@ -11,11 +25,8 @@ def rank_zero_only(func):
@wraps(func)
def wrapper(*args, **kwargs):
if local_rank != 0:
- return
+ return
result = func(*args, **kwargs)
return result
-
+
return wrapper
-
-
-
diff --git a/parakeet/utils/scheduler.py b/parakeet/utils/scheduler.py
index 97e98ec..4d41aca 100644
--- a/parakeet/utils/scheduler.py
+++ b/parakeet/utils/scheduler.py
@@ -1,3 +1,17 @@
+# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
import math
__all__ = ["SchedulerBase", "Constant", "PieceWise", "StepWise"]
@@ -24,7 +38,7 @@ class PieceWise(SchedulerBase):
self.xs = [item[0] for item in anchors]
self.ys = [item[1] for item in anchors]
self.num_anchors = len(self.xs)
-
+
def __call__(self, step):
i = 0
for x in self.xs:
@@ -34,8 +48,8 @@ class PieceWise(SchedulerBase):
return self.ys[0]
if i == self.num_anchors:
return self.ys[-1]
- k = (self.ys[i] - self.ys[i-1]) / (self.xs[i] - self.xs[i-1])
- out = self.ys[i-1] + (step - self.xs[i-1]) * k
+ k = (self.ys[i] - self.ys[i - 1]) / (self.xs[i] - self.xs[i - 1])
+ out = self.ys[i - 1] + (step - self.xs[i - 1]) * k
return out
@@ -47,7 +61,7 @@ class StepWise(SchedulerBase):
self.xs = [item[0] for item in anchors]
self.ys = [item[1] for item in anchors]
self.num_anchors = len(self.xs)
-
+
def __call__(self, step):
i = 0
for x in self.xs:
@@ -58,5 +72,4 @@ class StepWise(SchedulerBase):
return self.ys[-1]
if i == 0:
return self.ys[0]
- return self.ys[i-1]
-
+ return self.ys[i - 1]
diff --git a/setup.py b/setup.py
index ee5f215..0fa9eb7 100644
--- a/setup.py
+++ b/setup.py
@@ -48,7 +48,6 @@ setup_info = dict(
description='Speech synthesis tools and models based on Paddlepaddle',
long_description=long_description,
license='Apache 2',
-
python_requires='>=3.6',
install_requires=[
'numpy',
@@ -71,23 +70,18 @@ setup_info = dict(
'yacs',
'tensorboardX',
],
- extras_require={
- 'doc': ["sphinx", "sphinx-rtd-theme", "numpydoc"],
- },
+ extras_require={'doc': ["sphinx", "sphinx-rtd-theme", "numpydoc"], },
# Package info
packages=find_packages(exclude=('tests', 'tests.*')),
- zip_safe=True,
-
- classifiers = [
+ zip_safe=True,
+ classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Topic :: Scientific/Engineering :: Artificial Intelligence'
'License :: OSI Approved :: Apache2 License',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
- ],
-
- )
+ ], )
setup(**setup_info)