Working with Kaldi's IO¶
This tutorial shows how to read and write ark/scp files in Python.
Reading and Writing Alignment Information¶
The following class can be used to write alignment information to files:
IntVectorWriter
And the following classes can be used to read alignment information from files:
SequentialIntVectorReaderRandomAccessIntVectorReader
The following code shows how to write and read alignment information.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/usr/bin/env python3
import kaldi
wspecifier = 'ark,scp:/tmp/ali.ark,/tmp/ali.scp'
writer = kaldi.IntVectorWriter(wspecifier)
writer.Write(key='foo', value=[1, 2, 3])
writer.Write('bar', [10, 20])
writer.Close()
rspecifier = 'scp:/tmp/ali.scp'
reader = kaldi.SequentialIntVectorReader(rspecifier)
for key, value in reader:
print(key, value)
reader.Close()
reader = kaldi.RandomAccessIntVectorReader(rspecifier)
value1 = reader['foo']
print(value1)
value2 = reader['bar']
print(value2)
reader.Close()
|
Its output is
foo [1, 2, 3]
bar [10, 20]
[1, 2, 3]
[10, 20]
The output of the following command
$ copy-int-vector scp:/tmp/ali.scp ark,t:-
is
copy-int-vector scp:/tmp/ali.scp ark,t:-
foo 1 2 3
bar 10 20
LOG (copy-int-vector[5.5.792~1-f5875b]:main():copy-int-vector.cc:83) Copied 2 vectors of int32.
5 | wspecifier = 'ark,scp:/tmp/ali.ark,/tmp/ali.scp'
|
It creates a write specifier wspecifier indicating that
the alignment information is going to be written into files
/tmp/ali.ark and /tmp/ali.scp.
8 | writer.Write(key='foo', value=[1, 2, 3])
|
It writes a list [1, 2, 3] to file with key == foo.
Note that you can use keyword arguments while writing.
9 | writer.Write('bar', [10, 20])
|
It writes a list [10, 20] to file with key == bar.
10 | writer.Close()
|
It closes the writer.
Note
It is a best practice to close the file when it is no longer needed.
12 13 | rspecifier = 'scp:/tmp/ali.scp'
reader = kaldi.SequentialIntVectorReader(rspecifier)
|
It creates a sequential reader.
15 16 | for key, value in reader:
print(key, value)
|
It uses a for loop to iterate the reader.
18 | reader.Close()
|
It closes the reader.
20 | reader = kaldi.RandomAccessIntVectorReader(rspecifier)
|
It creates a random access reader.
21 22 | value1 = reader['foo']
print(value1)
|
It reads the value of foo and prints it out.
24 25 | value2 = reader['bar']
print(value2)
|
It reads the value of bar and prints it out.
26 | reader.Close()
|
Finally, it closes the reader.
The following code example achieves the same effect as the above one except that you do not need to close the file manually.
with¶1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/env python3
import kaldi
wspecifier = 'ark,scp:/tmp/ali.ark,/tmp/ali.scp'
with kaldi.IntVectorWriter(wspecifier) as writer:
writer.Write(key='foo', value=[1, 2, 3])
writer.Write('bar', [10, 20])
# Note that you do NOT need to close the file.
rspecifier = 'scp:/tmp/ali.scp'
with kaldi.SequentialIntVectorReader(rspecifier) as reader:
for key, value in reader:
print(key, value)
rspecifier = 'scp:/tmp/ali.scp'
with kaldi.RandomAccessIntVectorReader(rspecifier) as reader:
value1 = reader['foo']
print(value1)
value2 = reader['bar']
print(value2)
|
Reading and Writing Matrices¶
Using xfilename¶
The following code demonstrates how to read and write
FloatMatrix using xfilename.
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/env python3
import kaldi
m = kaldi.FloatMatrix(2, 2)
m[0, 0] = 10
m[1, 1] = 20
xfilename = '/tmp/lda.mat'
kaldi.write_mat(m, xfilename, binary=True)
g = kaldi.read_mat(xfilename)
print(g)
|
The output of the above program is
[
10 0
0 20 ]
5 6 7 | m = kaldi.FloatMatrix(2, 2)
m[0, 0] = 10
m[1, 1] = 20
|
It creates a FloatMatrix and sets its diagonal to [10, 20].
9 10 | xfilename = '/tmp/lda.mat'
kaldi.write_mat(m, xfilename, binary=True)
|
It writes the matrix to /tmp/lda.mat in binary format.
kaldi.write_mat is used to write the matrix
to the specified file. You can specify whether it is
written in binary format or text format.
12 13 | g = kaldi.read_mat(xfilename)
print(g)
|
It reads the matrix back and prints it to the console.
Note that you do not need to specify whether the file to
read is in binary or not. kaldi.read_mat will figure
out the format automatically.
Using specifier¶
The following code demonstrates how to read and write
FloatMatrix using specifier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #!/usr/bin/env python3
import numpy as np
import kaldi
wspecifier = 'ark,scp:/tmp/feats.ark,/tmp/feats.scp'
writer = kaldi.MatrixWriter(wspecifier)
m = np.arange(6).reshape(2, 3).astype(np.float32)
writer.Write(key='foo', value=m)
g = kaldi.FloatMatrix(2, 2)
g[0, 0] = 10
g[1, 1] = 20
writer.Write('bar', g)
writer.Close()
rspecifier = 'scp:/tmp/feats.scp'
reader = kaldi.SequentialMatrixReader(rspecifier)
for key, value in reader:
assert key in ['foo', 'bar']
if key == 'foo':
np.testing.assert_array_equal(value.numpy(), m)
else:
np.testing.assert_array_equal(value.numpy(), g.numpy())
reader.Close()
reader = kaldi.RandomAccessMatrixReader(rspecifier)
assert 'foo' in reader
assert 'bar' in reader
np.testing.assert_array_equal(reader['foo'].numpy(), m)
np.testing.assert_array_equal(reader['bar'].numpy(), g.numpy())
reader.Close()
|
6 7 8 | wspecifier = 'ark,scp:/tmp/feats.ark,/tmp/feats.scp'
writer = kaldi.MatrixWriter(wspecifier)
|
This creates a matrix writer.
10 11 | m = np.arange(6).reshape(2, 3).astype(np.float32)
writer.Write(key='foo', value=m)
|
It creates a Numpy array object of type np.float32 and
writes it to file with the key foo. Note that the type
of the Numpy array has to be of type np.float32.
The program throws if the type is not np.float32.
13 14 15 16 | g = kaldi.FloatMatrix(2, 2)
g[0, 0] = 10
g[1, 1] = 20
writer.Write('bar', g)
|
It creates a FloatMatrix and writes it to file
with the key bar.
Hint
kaldi.MatrixWriter accepts Numpy array objects of
type np.float32 as well as kaldi.FloatMatrix objects.
18 | writer.Close()
|
It closes the writer.
20 21 | rspecifier = 'scp:/tmp/feats.scp'
reader = kaldi.SequentialMatrixReader(rspecifier)
|
It creates a sequential matrix reader.
21 22 23 24 25 26 27 | reader = kaldi.SequentialMatrixReader(rspecifier)
for key, value in reader:
assert key in ['foo', 'bar']
if key == 'foo':
np.testing.assert_array_equal(value.numpy(), m)
else:
np.testing.assert_array_equal(value.numpy(), g.numpy())
|
It uses a for loop to iterate the sequential reader.
29 | reader.Close()
|
It closes the sequential reader.
31 | reader = kaldi.RandomAccessMatrixReader(rspecifier)
|
It creates a random access matrix reader.
32 33 | assert 'foo' in reader
assert 'bar' in reader
|
It uses in to test whether the reader contains a given key.
34 35 | np.testing.assert_array_equal(reader['foo'].numpy(), m)
np.testing.assert_array_equal(reader['bar'].numpy(), g.numpy())
|
It uses [] to read the value of a specified key.
36 | reader.Close()
|
It closes the random access reader.
The following code example achieves the same effect as the above one except that you do not need to close the file manually.
with¶1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #!/usr/bin/env python3
import numpy as np
import kaldi
wspecifier = 'ark,scp:/tmp/feats.ark,/tmp/feats.scp'
with kaldi.MatrixWriter(wspecifier) as writer:
m = np.arange(6).reshape(2, 3).astype(np.float32)
writer.Write(key='foo', value=m)
g = kaldi.FloatMatrix(2, 2)
g[0, 0] = 10
g[1, 1] = 20
writer.Write('bar', g)
rspecifier = 'scp:/tmp/feats.scp'
with kaldi.SequentialMatrixReader(rspecifier) as reader:
for key, value in reader:
assert key in ['foo', 'bar']
if key == 'foo':
np.testing.assert_array_equal(value.numpy(), m)
else:
np.testing.assert_array_equal(value.numpy(), g.numpy())
with kaldi.RandomAccessMatrixReader(rspecifier) as reader:
assert 'foo' in reader
assert 'bar' in reader
np.testing.assert_array_equal(reader['foo'].numpy(), m)
np.testing.assert_array_equal(reader['bar'].numpy(), g.numpy())
|