Project Setup Design
This document outlines how to set up a project structure in pstrain.
Overview
Project setup creates the initial directory structure and prepares the project for training. This is the first step before any training can begin.
Project Structure
Design for sharing resources across experiments:
project/
├── etc/
│ └── config.yaml # Project configuration
├── audio/ # Audio files (WAV format) - shared across experiments
├── shared/ # Shared resources across ALL experiments
│ ├── dictionary.dict # Main pronunciation dictionary
│ ├── filler.dict # Filler word dictionary
│ └── features/ # Extracted features (shared across experiments)
│ └── {feature_set_id}/ # Feature set identified by audio+feature config
│ ├── {fileid1}.mfc # Feature files (one per audio file)
│ ├── {fileid2}.mfc
│ ├── ...
│ ├── feat.params # Feature parameters
│ ├── global_mean # Global statistics
│ └── global_variance
└── experiments/ # Training experiments (isolated)
└── {experiment_name}/ # Individual experiment
├── models/ # Trained models (experiment-specific)
│ ├── ci/ # Context-Independent models
│ │ └── {config}/ # Model configuration (e.g., "baseline", "1g", "lda")
│ │ └── model/
│ │ ├── flat/ # Flat initialization models
│ │ └── hmm/ # Trained CI model files
│ └── cd/ # Context-Dependent models (future)
│ └── {config}/
│ └── model/
│ └── hmm/ # Trained CD model files
├── logs/ # Training logs
└── work/ # Working directory for training
Key Design Principles
Shared Resources at Project Level
audio/- All experiments use the same audio filesshared/dictionary.dict- All experiments use the same dictionaryshared/features/{feature_set_id}/- Features shared by experiments with same config
Feature Set Identification
Feature directory name (
feature_set_id) is deterministic based on:Audio configuration (sample rate, format)
Feature extraction configuration (num_ceps, filters, etc.)
Experiments with identical audio+feature config share the same feature directory
Different feature configs get different directories (e.g.,
mfcc_13,mfcc_39,lda_29)
Experiment Isolation
Each experiment has its own
models/,logs/, andwork/directoriesExperiments can reference shared features without copying them
Multiple experiments can run in parallel using the same features
Space Efficiency
Features are computed once per unique (audio, feature) configuration
No duplication of features across experiments
Experiments only store their unique outputs (models, logs)
Setup Requirements
Required Inputs
Configuration file (
etc/config.yaml)Project metadata (name, description)
Audio settings (sample rate, format)
Feature extraction settings
Training parameters
Dictionary and phoneset paths
Fileid list with transcripts (
etc/all.transcriptionor similar)Format: One line per utterance:
<fileid> <word1> <word2> ...Example:
arctic_a0001 hello worldFileid is the base name (without extension) of the audio file
Used to map audio files to their transcriptions
Audio files (in
audio/directory)Named by fileid:
{fileid}.wav(e.g.,arctic_a0001.wav)Must match fileids in transcription file
Format: WAV (16kHz recommended for speech)
One audio file per fileid
Pronunciation dictionary (
shared/dictionary.dict)Format: One entry per line:
<word> <phone1> <phone2> ...Example:
hello HH AH L OWMust contain all words used in transcripts
UTF-8 encoding
Phoneset (
shared/phoneset.txtor extracted from dictionary)List of all valid phones used in dictionary
Format: One phone per line (comments with #)
Can be extracted from dictionary automatically
Must include special phones (e.g., SIL for silence)
Optional Inputs
Filler dictionary (
shared/filler.dict) - Filler words (SIL, noise, etc.)Test split - Separate test transcription file (or split from all.transcription)
Outputs
Project structure - All directories created
Configuration file -
etc/config.yaml(created or validated)Dictionary files -
shared/dictionary.dict,shared/filler.dictPhoneset file -
shared/phoneset.txt(extracted from dictionary)Transcription file -
etc/all.transcription(validated)Directory structure -
audio/,shared/,experiments/
Setup Process
Step 1: Create Directory Structure
Create
etc/directoryCreate
audio/directoryCreate
shared/directoryCreate
experiments/directoryCreate
shared/features/directory
Step 2: Create/Validate Configuration File
Create
etc/config.yamlwith:Project metadata (name, description)
Audio settings (sample rate, format)
Feature extraction settings
Training parameters
Dictionary and phoneset paths
Or validate existing config file
Step 3: Prepare Dictionary and Phoneset
Copy dictionary file to
shared/dictionary.dictValidate dictionary format (UTF-8, one word per line)
Extract phoneset from dictionary to
shared/phoneset.txtCreate filler dictionary to
shared/filler.dict(if not provided)Validate all words in transcripts are in dictionary
Step 4: Prepare Transcription File
Create or validate
etc/all.transcriptionfileFormat:
<fileid> <word1> <word2> ...(one line per utterance)Validate format (UTF-8, proper structure)
Extract list of fileids from transcription file
Step 5: Prepare Audio Files
Copy or link audio files to
audio/directoryName files by fileid:
{fileid}.wav(must match transcription fileids)Validate audio files:
All fileids in transcription have corresponding audio files
Audio files are readable WAV format
Audio format matches config (sample rate, etc.)
Step 6: Validate Setup
Check all required directories exist
Validate dictionary format and phoneset
Validate transcription file format
Check all fileids have corresponding audio files
Verify all words in transcripts are in dictionary
Verify configuration is valid
CLI Command
pstrain setup [project_dir] [options]
Project Directory:
If
project_diris provided: Initialize project in that directory (create if needed)If
project_diris omitted: Initialize project in current directory (.)
Options:
--config <path>- Path to config file (or create default)--transcription <path>- Path to transcription file (fileid + transcripts)--audio <path>- Path to audio files directory (files named by fileid)--dictionary <path>- Path to pronunciation dictionary file--phoneset <path>- Path to phoneset file (or extract from dictionary)--filler-dict <path>- Path to filler dictionary (optional)--force- Force recreation if project exists
Examples:
Initialize in current directory:
cd my_project
pstrain setup \
--transcription /path/to/all.transcription \
--audio /path/to/audio \
--dictionary /path/to/dictionary.dict
Initialize in specified directory:
pstrain setup my_project \
--transcription /path/to/all.transcription \
--audio /path/to/audio \
--dictionary /path/to/dictionary.dict
Initialize with all options:
pstrain setup my_project \
--config /path/to/config.yaml \
--transcription /path/to/all.transcription \
--audio /path/to/audio \
--dictionary /path/to/dictionary.dict \
--phoneset /path/to/phoneset.txt
Transcription file format (etc/all.transcription):
arctic_a0001 hello world
arctic_a0002 this is a test
arctic_a0003 good morning
Audio file naming:
Fileid from transcription:
arctic_a0001Audio file:
audio/arctic_a0001.wavMust match exactly (case-sensitive)
Implementation for pstrain
Phase 0: Project Setup (NEW - First Priority)
TODO 0.1: Setup CLI Command
[ ] Create
pstrain/cli/setup.pymodule[ ] Add
pstrain setupcommand to main CLI[ ] Parse command-line arguments:
[ ]
project_dir(optional positional) - If provided, use that directory; if omitted, use current directory[ ]
--config,--transcription,--audio,--dictionary,--phoneset,--filler-dict[ ]
--forceflag
[ ] Resolve project directory:
[ ] If
project_dirprovided: create if needed, use absolute path[ ] If omitted: use
Path.cwd()(current directory)
[ ] Validate inputs
[ ] Call setup function
TODO 0.2: Setup Function
[ ] Create
pstrain/lib/setup.pymodule[ ] Implement
setup_project(project_dir: Path, ...)function[ ] Handle project directory:
[ ] Accept
project_diras Path (absolute or relative)[ ] Create directory if it doesn’t exist (when
project_diris provided)[ ] If directory exists and not empty, check
--forceflag
[ ] Create directory structure
[ ] Create default config file
[ ] Copy/prepare dictionary
[ ] Copy/link audio files
[ ] Prepare transcripts
[ ] Validate setup
[ ] Return setup status and paths
TODO 0.3: Configuration Management
[ ] Create
pstrain/lib/config.pymodule[ ] Implement config loading/saving
[ ] Create default config template
[ ] Validate config schema
[ ] Support config overrides
TODO 0.4: Dictionary and Phoneset Handling
[ ] Create
pstrain/lib/dictionary.pymodule[ ] Implement dictionary loading/validation
[ ] Support filler dictionary
[ ] Validate dictionary format (UTF-8, proper structure)
[ ] Create
pstrain/lib/phoneset.pymodule[ ] Implement phoneset loading/validation
[ ] Extract phoneset from dictionary
[ ] Validate dictionary phones against phoneset
[ ] Support phoneset file format (one phone per line, # comments)
TODO 0.5: Transcription File Handling
[ ] Create
pstrain/lib/transcription.pymodule[ ] Implement transcription file parsing
[ ] Format:
<fileid> <word1> <word2> ...(one line per utterance)[ ] Extract fileid list from transcription
[ ] Validate transcription format (UTF-8, proper structure)
[ ] Validate all words in transcripts are in dictionary
TODO 0.6: Feature Set Identification
[ ] Create
pstrain/lib/features.pymodule[ ] Implement
get_feature_set_id(audio_config, feature_config)function[ ] Generate deterministic identifier from audio + feature parameters
[ ] Use hash or descriptive name (e.g.,
mfcc_13,lda_29)[ ] Ensure same config always produces same feature_set_id
[ ] Document feature directory naming convention
TODO 0.7: Project Validation
[ ] Create
pstrain/lib/validate.pymodule[ ] Implement project structure validation
[ ] Check required files exist:
[ ] Configuration file
[ ] Transcription file
[ ] Dictionary file
[ ] Phoneset file (or extract from dictionary)
[ ] Validate file formats
[ ] Validate fileid matching:
[ ] All fileids in transcription have corresponding audio files
[ ] All audio files have corresponding transcriptions
[ ] Validate dictionary coverage:
[ ] All words in transcripts are in dictionary
[ ] All phones in dictionary are in phoneset
[ ] Check audio files are readable WAV format
[ ] Validate feature directory structure (if features exist)
Deliverables:
pstrain/cli/setup.py- Setup CLI commandpstrain/lib/setup.py- Setup implementationpstrain/lib/config.py- Configuration managementpstrain/lib/dictionary.py- Dictionary handlingpstrain/lib/phoneset.py- Phoneset handlingpstrain/lib/transcription.py- Transcription file handlingpstrain/lib/features.py- Feature set identificationpstrain/lib/validate.py- Project validationtests/test_setup.py- Unit testsDocumentation
Configuration File Format
# etc/config.yaml
project:
name: "my_project"
description: "Acoustic model training project"
version: "1.0.0"
audio:
sample_rate: 16000
format: "wav"
directory: "audio"
features:
num_ceps: 13
num_filters: 25
lower_freq: 133.33334
upper_freq: 6855.4976
preemphasis: 0.97
transform: "dct"
lifter: 22
agc: "max"
cmn: "batch"
varnorm: false
feature_type: "1s_c_d_dd"
dictionary:
main_dict: "shared/dictionary.dict"
filler_dict: "shared/filler.dict"
phoneset: "shared/phoneset.txt" # Can be extracted from dictionary
corpus:
transcription_file: "etc/all.transcription" # Fileid + transcripts
audio_dir: "audio" # Audio files named by fileid: {fileid}.wav
features:
# Feature directory is automatically determined by audio + feature config
# Path: shared/features/{feature_set_id}/
# feature_set_id is hash/identifier based on audio and feature parameters
# Multiple experiments with same config share the same feature directory
training:
ci:
n_iterations: 10
convergence_threshold: 0.001
min_iterations: 3
abeam: 1e-100
bbeam: 1e-100
varfloor: 0.0001
mixw_floor: 0.00001
topn: 1
experiments:
directory: "experiments"
default_name: "baseline"
Validation
After setup, validate:
[ ] All required directories exist
[ ] Configuration file is valid YAML
[ ] Transcription file exists and is valid format
[ ] Dictionary file exists and is readable
[ ] Phoneset file exists (or can be extracted from dictionary)
[ ] All fileids in transcription have corresponding audio files
[ ] All audio files are readable WAV format
[ ] All words in transcripts are in dictionary
[ ] All phones in dictionary are in phoneset
[ ] Project structure matches expected layout
File Format Details
Transcription File Format (etc/all.transcription)
Format 1: Simple (fileid + words)
<fileid1> <word1> <word2> <word3>
<fileid2> <word1> <word2>
<fileid3> <word1> <word2> <word3> <word4>
Format 2: Sphinx format (with sentence markers)
<s> <word1> <word2> <word3> </s> (<fileid1>)
<s> <word1> <word2> </s> (<fileid2>)
One line per utterance
First token is fileid (Format 1) or fileid in parentheses at end (Format 2)
Remaining tokens are words
UTF-8 encoding
Words must match dictionary entries
Fileid is base name without extension (e.g.,
arctic_a0001→ audio filearctic_a0001.wav)
Audio File Naming
Fileid from transcription:
arctic_a0001Audio file:
audio/arctic_a0001.wavMust match exactly (case-sensitive, no extension in fileid)
Integration with Workflows
Once project is set up:
Workflows can reference project structure
Config file provides paths to resources
Shared resources (dictionary, features) are accessible
Experiments can be created in
experiments/directory
Next Steps After Setup
Feature extraction - Extract features from audio
Data splitting - Split into train/test sets
Flat initialization - Initialize flat models
CI training - Train CI models
Design Notes
Shared resources - Dictionary, audio, and features are shared across experiments
Feature set identification - Features are stored in
shared/features/{feature_set_id}/wherefeature_set_idis deterministic based on audio+feature configSpace efficiency - Features computed once per unique config, shared by all experiments using that config
Experiment isolation - Each experiment has its own models and logs
Config-driven - All paths come from config file
Validation - Setup validates project structure before proceeding
Idempotent - Setup can be run multiple times safely (skips if exists)
Feature Sharing Design
Problem: Multiple experiments often use the same audio and feature extraction settings, but features are expensive to compute.
Solution: Features are stored in shared/features/{feature_set_id}/ where feature_set_id is a deterministic identifier based on:
Audio configuration (sample rate, format)
Feature extraction configuration (num_ceps, filters, transforms, etc.)
Benefits:
Features computed once per unique (audio, feature) configuration
All experiments with matching config automatically share features
No manual coordination needed - feature directory is determined by config
Experiments can run in parallel using the same features
Space efficient - no duplication of large feature files
Example:
Experiment
baselineusesmfcc_13features →shared/features/mfcc_13/Experiment
lda_v1useslda_29features →shared/features/lda_29/Experiment
baseline_v2also usesmfcc_13→ reusesshared/features/mfcc_13/(no recomputation)
Testing with CMU Arctic
For testing purposes, CMU Arctic corpus can be used:
Source: http://festvox.org/cmu_arctic/cmu_arctic/packed/
Format: Packed archives (tar.bz2) with audio and transcripts
Process: Download, extract, convert format, set up project
Note: See
docs/design/testing-with-cmu-arctic.mdfor details (local testing only, do not commit data/scripts)