Deepspeech - Build a language model

  • 实验环境

    • DeepSpeech version: v0.5.1
    • Tensorflow version: v1.11.0
    • 中文语音资料 data-thchs30
  • 目录结构

$ cd DeepSpeech
$ ls
corpus              # 存放语音资料
  |- data-thchs30/
  `- others
deepspeech          # DeepSpeech 代码库
deepspeech-utils    # DeepSpeech 的脚本工具
kenlm               # KenLM 代码库
projects            # 语音训练项目根目录
tensorflow          # Tensorflow 代码库
  • 安装 Bazel,用来编译 Tensorflow
$ wget https://github.com/bazelbuild/bazel/releases/download/0.15.0/bazel_0.15.0-linux-x86_64.deb
$ sudo dpkg -i bazel_0.15.0-linux-x86_64.deb
  • 创建版本切换脚本
$ mkdir -p deepspeech-utils/bin/
$ vim deepspeech-utils/bin/deepspeech-switch.sh
#!/bin/bash

set -xe

if [ $# -lt 1 ]; then
    echo "Usage: $(basename $0) VERSION [gpu|cpu]"
    exit 1
fi

if [ "$2" == "gpu" ]; then
    ARCH="gpu"
else
    ARCH="cpu"
fi

if [ ! -f DeepSpeech.py ]; then
    echo "Please make sure you run this from DeepSpeech's top level directory."
    exit 1
fi;

if [[ $ver != v* ]] ; then 
    VERSION=v$1
else
    VERSION=$1
fi

# switch to master
git checkout master

# reset
git reset HEAD --hard

# clean untracked files
git ls-files --other --exclude-standard | xargs -I '{}' -r rm '{}'

# skip smudge
git lfs install --skip-smudge

# pull latest
git pull

# reinstall smudge
git lfs install --force

# obtain native_client files
python util/taskcluster.py --branch $VERSION --target native_client/ --arch $ARCH

# switch to version
git checkout $VERSION

# uninstall python bindings
if [ "$(pip show deepspeech)" ]; then
    pip uninstall -y deepspeech
fi

if [ "$(pip show deepspeech-gpu)" ]; then
    pip uninstall -y deepspeech-gpu
fi

# install python bindings
PKG_VER=$(sed 's/v//g;' <<< $VERSION)

if [ "$ARCH" == "gpu" ]; then
    pip install deepspeech-gpu==$PKG_VER
else
    pip install deepspeech==$PKG_VER
fi
  • 获取 Deepspeech 并切换至最新稳定版 v0.5.1
$ cd ~/src
$ git clone https://github.com/mozilla/DeepSpeech deepspeech
$ cd deepspeech
$ ../deepspeech-utils/bin/deepspeech-switch.sh 0.5.1 gpu

Note: checking out 'v0.5.1'.
...
  • 安装所需 python 包
$ cd DeepSpeech/deepspeech
$ vim requirements.txt
将 tensorflow 改为 tensorflow-gpu

$ pip install -r requirements.txt
  • 获取 Tensorflow
$ cd ~/src
$ git clone https://github.com/mozilla/tensorflow/
$ cd tensorflow
$ git checkout v1.11.0
$ ln -s ../deepspeech/native_client native_client ./
  • 编译 Deepspeech with Tensorflow
$ ./configure
# Enable GPU...

$ bazel build -c opt --copt=-O3 --copt="-D_GLIBCXX_USE_CXX11_ABI=0" //native_client:libctc_decoder_with_kenlm.so
$ bazel build --config=monolithic -c opt --copt=-O3 --copt="-D_GLIBCXX_USE_CXX11_ABI=0" --copt=-fvisibility=hidden //native_client:libdeepspeech.so //native_client:generate_trie
$ cd ../deepspeech/native_client
$ make deepspeech
  • 创建语音资料库初始化脚本
$ vim deepspeech-utils/bin/build-corpus.rb
$ mkdir -p projects/thchs-1000
$ cd projects/thchs-1000
$ ../../deepspeech-utils/bin/build-corpus.rb -i ../../corpus/data-thchs30/ -n 1000

Total 13388 audio files in repository:
1) ../../corpus/data-thchs30/
Build links for data (1000)...
Build links for train (800)...
Build links for dev (200)...
Build links for test (100)...
#!/usr/bin/ruby

require 'set'
require 'optparse'
require 'ostruct'

def change_ext(filename, new_ext)
    dirname = File.dirname(filename)
    name = File.basename(filename, File.extname(filename))
    File.join(dirname, name + new_ext)
end

def link_file(src_file, dest_dir)
    if not Dir.exist?(dest_dir)
        Dir.mkdir(dest_dir)
    end
    newfile = File.join(dest_dir, File.basename(src_file))
    if File.exist?(newfile) or File.symlink?(newfile)
        File.delete newfile
    end
    File.symlink(File.absolute_path(src_file), newfile)
end

def make_links(src_file_list, dest_dir, max_count)
    if Dir.exist?(dest_dir)
        $stderr.puts "Skipped: directory `#{dest_dir}` already exist."
    else
        src_file_list.sample(max_count).each { |wavfile|
            trnfile = wavfile + '.trn'
            link_file(wavfile, dest_dir)
            link_file(trnfile, dest_dir)
        }
    end
end

def get_audio_files(src_dir_list)
    src_dir_list.map { |src_dir|
        Dir.glob(File.join(src_dir, '**', '*.wav'))
    }.flatten.select { |wavfile|
        trnfile = wavfile + '.trn'
        File.exist?(trnfile)
    }.uniq
end

def parse_args(args)
    options = OpenStruct.new
    options.max_num = 100
    options.input_dir_list = []
    
    opt_parser = OptionParser.new do |opts|
        opts.banner = "Usage: deepspeech-prep-data.rb [OPTIONS]"
        opts.separator ''
        opts.separator 'Options:'

        opts.on("-i", "--input DIR", "the original audio data directory") do |dir|
            if not Dir.exist?(dir)
                raise "Path not found: #{dir}."
            end
            options.input_dir_list << dir
        end

        opts.on("-n", "--max-num NUMBER", Integer, "max number of audio files to process") do |n|
            if n <= 0
                raise "Number should be greater than 0."
            end
            options.max_num = n
        end

        opts.on("-h", "--help", "show this message") do
            puts opts
            exit
        end
    end

    opt_parser.parse!(args)
    raise OptionParser::MissingArgument if options.input_dir_list.empty?
    return options
end

def min(a, *b)
    arr = [a]
    arr += b
    return arr.min
end

def prep_data(audio_dir_list, max_count)
    audio_files = get_audio_files(audio_dir_list)
    total_count = audio_files.count
    puts "Total #{total_count} audio files in repository: \n#{audio_dir_list.map.with_index { |dir, i| "#{i+1}) #{dir}" }.join("\n")}"

    if total_count <= 0
        puts "Exit."
        exit 1
    end

    n_train =  (max_count * 0.8).floor
    n_dev =  (max_count * 0.2).floor
    n_test = min(100, (max_count * 0.1).floor)

    puts "Build links for data (#{max_count})..."
    make_links(audio_files, 'data', max_count)
    
    puts "Build links for train (#{n_train})..."
    make_links(audio_files, 'train', n_train)

    puts "Build links for dev (#{n_dev})..."
    make_links(audio_files, 'dev', n_dev)

    puts "Build links for test (#{n_test})..."
    make_links(audio_files, 'test', n_test)
end

def main
    opts = parse_args(ARGV)
    prep_data(opts.input_dir_list, opts.max_num)
end

main
  • 创建语音资料的 CSV 生成脚本
$ vim deepspeech-utils/bin/deepspeech-gencsv.rb
#!/usr/bin/ruby

# CSV file generator for DeepSpeech

require 'set'
require 'optparse'
require 'ostruct'

INSERT_BLANKS = false

class AudioItem
    attr_accessor :path
    attr_accessor :size
    attr_accessor :transcript
end

def alphabet_en
    s = Set.new
    s.merge ('a'..'z').to_a
    s.merge ('0'..'9').to_a
    return s
end

def punctuations_en
    s = "! ? : ; , . ' \" ( ) [ ] < > { } - ~"
    s.chars.select { |c| not c.strip.empty? }
end

def punctuations_cn
    s = "!?:;,。.· 、‘’“”()【】《》〉「」—─~… \u{feff}"
    s.chars.select { |c| not c.strip.empty? }
end

def delimiters_en
     s = "! ? : ; , ."
     s.chars.select { |c| not c.strip.empty? }
end

def delimiters_cn
    s = '!?:;,。…'
    s.chars.select { |c| not c.strip.empty? }
end

def punctuations_regex
    s = punctuations_en.map { |c| "\\#{c}" }.join + punctuations_cn.join
    return /[#{s}]/
end

def delimiters_regex
    s = delimiters_en.map { |c| "\\#{c}" }.join + delimiters_cn.join
    return /[#{s}]/
end

def load_vocabularies(filename)
    if File.exist?(filename)
        set = Set.new
        IO.readlines(filename).each { |line|
            voc = get_phrases(line.downcase)
            set.merge(voc)
        }
        return set
    else
        raise "File not found: #{filename}."
    end
end

def insert_blanks(s)
    s.gsub(/\s+/, '').chars.join(' ')
end

def append_alphabet(alphabet_set, string_arr)
    string_arr.each { |s|
        alphabet_set.merge(s.chars)
    }
end

def get_phrases(transcript)
    transcript.split(delimiters_regex)
        .map { |s| s.gsub(punctuations_regex, '') }
        .select { |s| not s.empty? }
        .map { |s| INSERT_BLANKS ? insert_blanks(s) : s }
end

def process_corpus(data_dir, csv_file, alphabet_file, voc_file, max_num, text_book)
    alphabet = Set.new([' '])
    voc = Set.new
    arr = Array.new
    n = 0

    files = Dir.glob(File.join(data_dir, '**', '*.wav'))
    files.each { |wavfile|
        if not max_num.nil? and n >= max_num
            break
        end

        n = n + 1
        size = File.size(wavfile)
        txtfile = wavfile + '.trn'

        if File.exist?(txtfile)
            text = load_transcript(txtfile)
            v = get_phrases(text)
            voc.merge(v)
            
            item = AudioItem.new
            item.path = File.absolute_path(wavfile)
            item.size = size
            item.transcript = INSERT_BLANKS ? insert_blanks(text) : text
            arr.push item
        else
            raise "Text file not found: #{txtfile}."
        end
    }

    if not text_book.nil? 
        if File.exist?(text_book)
            puts "Load phrases from book: #{text_book}..."
            voc.merge(load_vocabularies(text_book))
        elsif
            raise "Text book not exist: #{text_book}."
        end
    end

    append_alphabet(alphabet, alphabet_en)
    append_alphabet(alphabet, arr.map { |x| x.transcript })
    append_alphabet(alphabet, voc)
    save_csv(arr, csv_file)
    save_alphabet(alphabet, alphabet_file)
    save_vocabulary(voc, voc_file)
end

def load_transcript(filename)
    filename = File.absolute_path(filename)
    text = IO.readlines(filename)
        .map { |line| line.strip }
        .select { |line| not line.empty? }
        .first

    if text.nil?
        raise "Transcript of #{filename} is empty"
    end

    dir = File.dirname(filename)
    linkname = File.join(dir, text)
    # if File.exist?(linkname)
    if text.start_with?('..')
        return load_transcript(linkname)
    else
        return text.downcase
    end
end

def save_csv(arr, filename)
    if not filename.nil?
        out = File.new(filename, "w")
        out.puts 'wav_filename,wav_filesize,transcript'
        arr.each { |item|
            out.puts "#{item.path},#{item.size},#{item.transcript}"
        }
    end
end

def save_vocabulary(voc, filename)
    if not filename.nil?
        out = File.new(filename, "w")
        voc.each { |line|
            out.puts line
        }
        out.close
    end
end

def save_alphabet(chars, filename)
    if not filename.nil?
        out = File.new(filename, "w")
        out.puts '# Each line in this file represents the Unicode codepoint (UTF-8 encoded)'
        out.puts '# # associated with a numeric label.'
        out.puts '# # A line that starts with # is a comment. You can escape it with \# if you wish'
        out.puts '# # to use \'#\' as a label.'

        chars.each { |ch|
            out.puts ch
        }

        out.puts '# The last (non-comment) line needs to end with a newline.'
        out.close
    end
end

def parse_args(args)
    options = OpenStruct.new
    opt_parser = OptionParser.new do |opts|
        opts.banner = "Usage: deepspeech-gencsv [OPTIONS]"
        opts.separator ''
        opts.separator 'Options:'

        opts.on("-i", "--input DIR", "the audio data directory") do |dir|
            if not Dir.exist?(dir)
                raise "Path not found: #{dir}."
            end
            options.input = dir
        end

        opts.on("-o", "--output FILE", "save to this CSV file") do |csv|
            options.output = csv
        end

        opts.on("-a", "--alphabet FILE", "generate alphabet file") do |file|
            options.alphabet = file
        end

        opts.on("-v", "--vocabulary FILE", "generate vocabulary file") do |file|
            options.vocabulary = file
        end

        opts.on("-n", "--max-num NUMBER", Integer, "max number of audio files to process") do |n|
            options.max_num = n
        end

        opts.on("-t", "--text-book FILE", "text book with phrases") do |file|
            options.text_book = file
        end

        opts.on_tail("-h", "--help", "show this message") do
            puts opts
            exit
        end
    end

    opt_parser.parse!(args)
    raise OptionParser::MissingArgument if options.input.nil?
    return options
end

def main
    opts = parse_args(ARGV)
    process_corpus(opts.input, opts.output, opts.alphabet, opts.vocabulary, opts.max_num, opts.text_book)
end

main
  • 创建语音训练模型的生成脚本
$ vim deepspeech-utils/bin/genlm.sh
#!/bin/sh

set -xe

if [ "$#" -lt 1 ]; then
    echo "Usage: $0 AUDIO_DIR [PREFIX]"
    exit 1
fi

if [ ! -d $1 ]; then
    echo "Directory not found: $1"
    exit 2
fi

DATA_ROOT=$(realpath $1)
DEEPSPEECH_ROOT=~/src/Deepspeech/deepspeech

if [ $2 ]; then
    prefix=$2
else
    prefix="$(basename $DATA_ROOT)"
fi

genapp=$(dirname "$0")/deepspeech-gencsv.rb

# remove checkpoints
rm -rf ~/.local/share/deepspeech/$prefix/

# full scan
echo 'Performing a full scan...'
ruby $genapp -i $DATA_ROOT -o $DATA_ROOT/$prefix-full.csv -a $DATA_ROOT/$prefix-alphabet.txt -v $DATA_ROOT/$prefix-vocabulary.txt # --text-book $DATA_ROOT/book.txt

# train
echo 'Generating train.csv...'
ruby $genapp -i $DATA_ROOT/train -o $DATA_ROOT/$prefix-train.csv 

# dev
echo 'Generating dev.csv...'
ruby $genapp -i $DATA_ROOT/dev -o $DATA_ROOT/$prefix-dev.csv

# test
echo 'Generating test.csv...'
ruby $genapp -i $DATA_ROOT/test -o $DATA_ROOT/$prefix-test.csv

# arpa
echo 'Generating ARPA file for binary build...'
lmplz -S 50% --text $DATA_ROOT/$prefix-vocabulary.txt --arpa $DATA_ROOT/$prefix-words.arpa --o 4 --discount_fallback

# lm.binary
# ref: https://github.com/mozilla/DeepSpeech/issues/1407
echo 'Generating lm.binary...'
build_binary trie -q 16 -b 7 -a 64 $DATA_ROOT/$prefix-words.arpa $DATA_ROOT/$prefix-lm.binary

# trie
echo 'Generating trie...'
$DEEPSPEECH_ROOT/native_client/generate_trie \
    $DATA_ROOT/$prefix-alphabet.txt \
    $DATA_ROOT/$prefix-lm.binary \
    $DATA_ROOT/$prefix-vocabulary.txt \
    $DATA_ROOT/$prefix-trie

echo 'Done.'
  • 生成模型
$ cd DeepSpeech/projects/thchs-1000
$ ../../deepspeech-utils/bin/genlm.sh .

+ [ 1 -lt 1 ]
+ [ ! -d . ]
+ realpath .
+ DATA_ROOT=/home/ken/src/DeepSpeech/projects/thchs-1000
+ DEEPSPEECH_ROOT=/home/ken/src/Deepspeech/deepspeech
+ [ ]
+ basename /home/ken/src/DeepSpeech/projects/thchs-1000
+ prefix=thchs-1000
+ dirname ../../deepspeech-utils/bin/genlm.sh
+ genapp=../../deepspeech-utils/bin/deepspeech-gencsv.rb
+ rm -rf /home/ken/.local/share/deepspeech/thchs-1000/
+ echo Performing a full scan...
Performing a full scan...
+ ruby ../../deepspeech-utils/bin/deepspeech-gencsv.rb -i /home/ken/src/DeepSpeech/projects/thchs-1000 -o /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-full.csv -a /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-alphabet.txt -v /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-vocabulary.txt
+ echo Generating train.csv...
Generating train.csv...
+ ruby ../../deepspeech-utils/bin/deepspeech-gencsv.rb -i /home/ken/src/DeepSpeech/projects/thchs-1000/train -o /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-train.csv
+ echo Generating dev.csv...
Generating dev.csv...
+ ruby ../../deepspeech-utils/bin/deepspeech-gencsv.rb -i /home/ken/src/DeepSpeech/projects/thchs-1000/dev -o /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-dev.csv
+ echo Generating test.csv...
Generating test.csv...
+ ruby ../../deepspeech-utils/bin/deepspeech-gencsv.rb -i /home/ken/src/DeepSpeech/projects/thchs-1000/test -o /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-test.csv
+ echo Generating ARPA file for binary build...
Generating ARPA file for binary build...
+ lmplz -S 50% --text /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-vocabulary.txt --arpa /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-words.arpa --o 4 --discount_fallback
=== 1/5 Counting and sorting n-grams ===
Reading /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-vocabulary.txt
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
****************************************************************************************************
Unigram tokens 17357 types 8091
=== 2/5 Calculating and sorting adjusted counts ===
Chain sizes: 1:97092 2:2912452352 3:5460848128 4:8737356800
Substituting fallback discounts for order 3: D1=0.5 D2=1 D3+=1.5
Statistics:
1 8091 D1=0.709526 D2=1.15906 D3+=1.584
2 17265 D1=0.954478 D2=1.48329 D3+=1.78039
3 17291 D1=0.994003 D2=1.88531 D3+=3
4 16472 D1=0.5 D2=1 D3+=1.5
Memory estimate for binary LM:
type      kB
probing 1304 assuming -p 1.5
probing 1538 assuming -r models -p 1.5
trie     662 without quantization
trie     422 assuming -q 8 -b 8 quantization
trie     628 assuming -a 22 array pointer compression
trie     388 assuming -a 22 -q 8 -b 8 array pointer compression and quantization
=== 3/5 Calculating and sorting initial probabilities ===
Chain sizes: 1:97092 2:276240 3:345820 4:395328
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
####################################################################################################
=== 4/5 Calculating and writing order-interpolated probabilities ===
Chain sizes: 1:97092 2:276240 3:345820 4:395328
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
####################################################################################################
=== 5/5 Writing ARPA model ===
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
****************************************************************************************************
Name:lmplz      VmPeak:0 kB     VmRSS:3932 kB   RSSMax:3358500 kB       user:0.578125   sys:2.67188     CPU:3.25       real:3.36821
+ echo Generating lm.binary...
Generating lm.binary...
+ build_binary trie -q 16 -b 7 -a 64 /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-words.arpa /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-lm.binary
Reading /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-words.arpa
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
****************************************************************************************************
Identifying n-grams omitted by SRI
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
****************************************************************************************************
Quantizing
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
****************************************************************************************************
Writing trie
----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100
****************************************************************************************************
SUCCESS
+ echo Generating trie...
Generating trie...
+ /home/ken/src/Deepspeech/deepspeech/native_client/generate_trie /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-alphabet.txt /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-lm.binary /home/ken/src/DeepSpeech/projects/thchs-1000/thchs-1000-trie
+ echo Done.
Done.
  • 待训练的目录结构
$ cd DeepSpeech/projects/thchs-1000
$ ll

total 4184
drwxr-xr-x 1 ken ken    4096 Oct 27 22:13 data/
drwxr-xr-x 1 ken ken    4096 Oct 27 22:13 dev/
drwxr-xr-x 1 ken ken    4096 Oct 27 22:13 test/
-rw-r--r-- 1 ken ken   11431 Oct 27 23:15 thchs-1000-alphabet.txt
-rw-r--r-- 1 ken ken   37060 Oct 27 23:15 thchs-1000-dev.csv
-rw-r--r-- 1 ken ken  391554 Oct 27 23:15 thchs-1000-full.csv
-rw-r--r-- 1 ken ken 1283494 Oct 27 23:15 thchs-1000-lm.binary
-rw-r--r-- 1 ken ken   18482 Oct 27 23:15 thchs-1000-test.csv
-rw-r--r-- 1 ken ken  149771 Oct 27 23:15 thchs-1000-train.csv
-rw-r--r-- 1 ken ken  200299 Oct 27 23:15 thchs-1000-trie
-rw-r--r-- 1 ken ken  102973 Oct 27 23:15 thchs-1000-vocabulary.txt
-rw-r--r-- 1 ken ken 2068961 Oct 27 23:15 thchs-1000-words.arpa
drwxr-xr-x 1 ken ken    4096 Oct 27 22:13 train/
  • 运行模型训练
#!/bin/bash
set -xe

if [ "$#" -lt 1 ]; then
    echo $#
    echo "Usage: $(basename $0) DATA_DIR [EPOCH] [PREFIX]"
    exit 1
fi

DATA_DIR="$(readlink -f $1)"
EPOCH=${2:-"10"}
prefix=${3:-$(basename $DATA_DIR)}

DEEPSPEECH_ROOT="$HOME/src/Deepspeech/deepspeech"
pushd $DEEPSPEECH_ROOT

if [ ! -f DeepSpeech.py ]; then
    echo "Please make sure you run this from DeepSpeech's top level directory."
    exit 2
fi;

if [ ! -d $DATA_DIR ]; then
    echo "Directory does not exist: $1"
    exit 3
fi

ALPHABET="$DATA_DIR/$prefix-alphabet.txt"
LM_BINARY="$DATA_DIR/$prefix-lm.binary"
LM_TRIE="$DATA_DIR/$prefix-trie"
TRAIN_CSV="$DATA_DIR/$prefix-train.csv"
DEV_CSV="$DATA_DIR/$prefix-dev.csv"
TEST_CSV="$DATA_DIR/$prefix-test.csv"

BATCH_SIZE=10

# check directory if exist
declare -a files=(
    $ALPHABET
    $TRAIN_CSV
    $DEV_CSV
    $TEST_CSV
)

for file in "${files[@]}"
do
    if [ ! -f "$file" ]; then
        echo "File not found: $file"
        exit 100
    fi;
done

if [ -d "${COMPUTE_KEEP_DIR}" ]; then
    checkpoint_dir=$COMPUTE_KEEP_DIR
else
    checkpoint_dir=$(python -c "from xdg import BaseDirectory as xdg; print(xdg.save_data_path(\"deepspeech/$prefix\"))")
fi

time python -u DeepSpeech.py \
  --alphabet_config_path $ALPHABET \
  --lm_binary_path $LM_BINARY \
  --lm_trie_path $LM_TRIE \
  --train_files $TRAIN_CSV \
  --dev_files $DEV_CSV \
  --test_files $TEST_CSV \
  --train_batch_size $BATCH_SIZE \
  --dev_batch_size $BATCH_SIZE \
  --test_batch_size $BATCH_SIZE \
  --n_hidden 512 \
  --learning_rate 0.0001 \
  --epoch $EPOCH \
  --checkpoint_dir "$checkpoint_dir" \
  --export_dir "$DATA_DIR" \
  --log_level 0 \
  --summary_secs 3 \
  "$@" \
  | tee "$DATA_DIR/$prefix-$(date +%Y%m%d).log"

popd
$ ./deepspeech-run.sh .
  • 用TensorBoard查看
$ tensorboard -logdir .local/share/deepspeech/summaries/
TensorBoard 1.6.0 at http://ubuntu1080:6006 (Press CTRL+C to quit)