『Pythonで学ぶ音声合成』をWindows10でやってみる(第4章)

はじめに

Pythonで学ぶ音声合成』で音声合成の基礎を身に着けたかったため、Windows環境で実践してみました。 ただ、Windows環境は公式サポートがされていないようで様々なエラーに見舞われたため、その対処を記録します。 動作確認として、深層学習が含まれない第4章の内容まで読み進めました。

プログラミング周りが初心者のため、変な記述があるかもしれませんがご了承ください。

環境構築

環境構築の手順は金子邦彦研究室のサイトを参考にしました。 www.kkaneko.jp

バージョンは Python 3.9.7, CUDA 11.1, cuDNN 8.2.3, PyTorch 1.9.0 を使うことにしました。 また、C++周りは Visual Studio 2019 Community をインストールしました。

Windows固有のエラー対応

ttslearn に含まれる pyopenjtalk がpip installできない

環境構築でインストールしたVisual Basic 2019 Community に含まれるCMakeにPATHを通すことで解決しました。自分の環境では、

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin

でした。以下のサイトを参照しました。 teitoku-window.hatenablog.com

librosaが管理者権限でないとimportできない

C:\Program Files\Python39\Lib\site-packages\librosa のフォルダプロパティを開き、Usersのアクセス許可で「書き込み」を許可すれば通るようになりました。pythonのインストールを全ユーザーで行ったため?

from ttslearn.dnntts import DNNTTS などができない

ttslearn の pretraind にある init.py が os.environ["HOME"] を使用しているものの、環境変数HOMEが無いというエラーのようです。ユーザー環境変数HOME を C:\Users\[ユーザー名] で追加したら通るようになりました。

2021/9/15にGitHubで修正済み

ターミナル出力関係

想定されているjupyter notebookではなく、PowerShellpythonを実行しているため、出力時にはファイルに書き出すようにしました。

グラフが出力されない(ターミナルに入力時)

plt.show() でグラフ描画の指示をする。

または、plt.savefig('out.png')として、pngファイルを作成して確認する。ttslearn.notebooksavefigも実行できたので、公式ドキュメントに従ってファイルを作成しても大丈夫です。

wavデータが聞けない(ターミナルに入力時)

from IPython.display import AudioAudio(wav, rate=sr)の代わりに、scipy.io.wavfile.write でwavファイルを作成して聞くことにする。

from scipy.io.wavfile import write
write('out.wav', sr, wav)

を実行する。

上記の方法で作成したwavファイルの音声が大音量・ノイズまみれになる

上記の方法で、逆短時間フーリエ変換(ISTFT)や位相復元後のデータからwavファイルを作成すると、聞くに堪えない異常なwavファイルが作成されます。引数が浮動小数点型float32にも関わらず、scipy.io.wavfile.write で指定されている値の範囲[-1.0, 1.0]を外れているためです。

例えば、p.84のISTFT後でwrite('istft.wav', sr, x_hat)を実行すると発生するので、write('istft.wav', sr, x_hat.astype(np.int16))と整数型int16に型変換を行ってから出力します。

誤植

p.78 フーリエ変換のグラフの周波数がおかしい

freqは大きい整数どうしの掛け算が含まれるので、np.arnge(len(X)) * srが先に行われると桁あふれを起こします。環境によって結果が変わるようです。

freq = np.arange(len(X)) / len(X) * sr / 2 

などとして解決します。2021/9/21にGithubでは修正済み

p.82 stft関数の定義

flame_shiftは関数内の変数ではないので、M = (len(x) - N) // S + 1と修正する。

おわりに

とりあえずWindowsでも読み進めて行けるのではという希望が持てました。Visual Basicのインストールと環境変数PATH、HOMEを解決すれば大丈夫そうです。 亀の歩みで第5章以降も読み進めていけたらと思います。

100℃の水と0℃の水は何℃になるか

はじめに

以下の問題を考えてみましょう。

100℃の水と0℃の水を同じ物質量だけ用意します。それらを混ぜ合わせたとき何℃になるでしょう?
(ただし熱のやり取りは外界としないものとします。比熱も一定であるとします。体積膨張なども無視できるとします。)


「100℃と0℃なので50℃!」と即答された方、正解です。後で確認するようにエネルギー保存則から計算できます。

それでは次の問題はどうでしょう。

100℃の水と0℃の水を同じ物質量だけ用意します。それらを可逆に同じ温度にしたとき何℃になるでしょう?何らかの熱機関を使っても良いものとします。
(ただし熱のやり取りは熱機関以外とはしないものとします。比熱も一定であるとします。体積膨張なども無視できるとします。)


可逆という言葉が出てきました。断熱的に(仕事のみによって)変化させて元に戻すことができるという意味です。

先程の100℃の水と0℃の水を単に混ぜて50℃の水を作るのは不可逆です。50℃の水が勝手に100℃の水と0℃の水になることはありません。熱力学第二法則に反してしまいます。 また、何らかの仕事で元に戻そうとしても、内部エネルギーの合計は変わっていないため、熱力学第一法則に反してしまいます。

もし可逆に同じ温度にできたならば、仕事をする余地を考えて50℃より低くなっていそうです。そのようなことは出来るのでしょうか?

内部エネルギー

手始めに、この系の内部エネルギー Uを設定します。比熱 Cが一定であるため、絶対温度 T、物質量 Nのとき

 \displaystyle
U = CNT

と書くことができます*1。エネルギーの原点を適当にずらして比例式にしています。

単位物質量あたりの内部エネルギー u = U/Nにすると、

 \displaystyle
u = CT

です。

単純に混ぜた場合

では、最初の100℃の水と0℃の水を単純に混ぜた場合を考えます。一般化しながら話を進めるため、 T_0  = 273.15 \mathrm{K} (= 0 ^{\circ} \mathrm{C}) T_1 = 373.15 \mathrm{K} (= 100 ^{\circ} \mathrm{C})と設定しておきます。

それぞれ物質量 Nだけあるとして、混ぜる前の内部エネルギーは、温度 T_0の方は U_0 =CNT_0、温度 T_1の方は U_1 =CNT_1です。そのときの内部エネルギーの総和は、

 \displaystyle
U_{\mathrm{sum}} = U_0 + U_1 = CN(T_0 + T_1)

となります。一方で、混ぜたあとの温度を[tex: T{\mathrm{mix}}]とすると、混ぜたことで物質量が 2Nとなっているため、内部エネルギー[tex: U{\mathrm{mix}}]は、

 \displaystyle
U_{\mathrm{mix}} = 2CNT_{\mathrm{mix}}

と書けます。仕事も熱も外部とやり取りしていないため、熱力学第一法則より、内部エネルギーは不変で U _{\mathrm{sum}} = U _{\mathrm{mix}} です。したがって、混ぜたあとの温度は

 \displaystyle
T_{\mathrm{mix}} = \frac{T_0 + T_1}{2}

と求まります。やはり、平均で求めて良いことが分かりました。 T_0  = 0 ^{\circ} \mathrm{C} T_1 = 100 ^{\circ} \mathrm{C}のときは、 T_{\mathrm{mix}} = 50 ^{\circ} \mathrm{C}です*2

エントロピー

次に、可逆に同じ温度にする場合を考えるために、エントロピー Sを求めておきます。単位物質量あたりのエントロピー s = S/Nを考えると、

 \displaystyle
\mathrm{d}s = \frac{1}{T} \mathrm{d}u

の関係あります*3 uは単位物質量あたりの内部エネルギーです。内部エネルギーの表式を代入して、

 \displaystyle
\mathrm{d}s = \frac{C}{u} \mathrm{d}u

として、これを積分することで、

 \displaystyle
s = s_0 + C \log \left( \frac{u}{u_0} \right) = s_0 + C \log \left( \frac{T}{T_0} \right)

と単位物質量あたりのエントロピー sの表式が得られます。物質量 Nのときのエントロピー S

 \displaystyle
S = \frac{N}{N_0} S_0 + CN \log \left( \frac{T}{T_0} \right)

となります。

以下では、温度 T_0でのエントロピー S_0 = 0と基準にとって計算を進めます。

 \displaystyle
S = CN \log \left( \frac{T}{T_0} \right)

エントロピー原理

熱力学の定理に「エントロピー原理」があります*4。これは、断熱過程のみでの状態変化が可能かどうかはエントロピーの大小のみによって知ることができるというものです。

詳しく書くと、エントロピー原理によって、熱平衡状態 Aエントロピー S_A)から熱平衡状態 Bエントロピー S_B)へ断熱過程のみで到達できることと、 S_A \leq S_Bであることが必要十分条件となります。

特に、熱平衡状態 Aと熱平衡状態 Bの変化が可逆で、どちらからも他方に断熱過程で変化できるとき、 S_A \leq S_Bかつ S_A \geq S_Bでなくてはならないので、

 \displaystyle
S_A = S_B

が言えます。可逆であることは、エントロピーが等しいと読み替えて良いことが分かりました。

可逆操作で同じ温度にした場合

準備が整ったので、可逆に同じ温度にした場合を考えていきます。 それぞれ物質量 Nだけあるとして、混ぜる前のエントロピーは、温度 T_0の方は S_0 = 0、温度 T_1の方は S_1 =CN \log (T_1/T_0) です。エントロピーの総和は、

 \displaystyle
S_{\mathrm{sum}} = S_0 + S_1 = CN \log \left( \frac{T_1}{T_0} \right)

となります。一方で、可逆操作後の温度を T _{\mathrm{rev}}とすると、その温度の物質量が 2Nであるため、可逆操作後のエントロピー S _{\mathrm{rev}}は、

 \displaystyle
S_{\mathrm{rev}} = 2CN \log \left( \frac{T_{\mathrm{rev}}}{T_0} \right)

と書けます。可逆の場合のエントロピー原理より、 S _{\mathrm{sum}} = S _{\mathrm{rev}} です。 \logを整理しながら比較すると、可逆操作後の温度は

 \displaystyle
T_{\mathrm{rev}} = \sqrt{T_0 T_1}

と求まります。単純に混ぜた時が相加平均だったのに対して、こちらは温度の相乗平均になっています。

「相乗平均 \leq相加平均」なので、可逆操作後の温度 T _{\mathrm{rev}}は単純に混ぜたあとの温度 T_{\mathrm{mix}}より低くなります。

 \displaystyle
T_{\mathrm{rev}} \leq T_{\mathrm{mix}}

また、内部エネルギーは可逆操作を経て、外界に何らかの仕事を行い、充電池やバネなどの位置エネルギーとして蓄えられることになります。減少分の内部エネルギーは、

 \displaystyle
\varDelta U = U_{\mathrm{sum}} - U_{\mathrm{rev}} = CN(T_{1} + T_{2} - 2 T_{\mathrm{rev}}) = 2CN(T_{\mathrm{mix}} - T_{\mathrm{rev}})

と計算できます。

 T_0  = 273.15 \mathrm{K} T_1 = 373.15 \mathrm{K}として実際どうなるのか見てみます。なお、ここでの計算は比が含まれるため、絶対温度で行わななければなりません。

 \displaystyle
T_{\mathrm{rev}} = \sqrt{T_0 T_1} \simeq 319.26 \mathrm{K} (=46.11 ^{\circ} \mathrm{C})

可逆に操作することで、100℃の水と0℃の水から約46.1℃の水が生まれることが分かります。

ついでに水1kgのときに、どれくらいのエネルギーを仕事として取り出したのか見ておきます。水の比熱は、カロリーの定義より*5

 \displaystyle
C  =1.0 \ \mathrm{kcal \ kg^{-1} \ K^{-1}} \simeq 4.2 \ \mathrm{kJ \ kg^{-1} \ K^{-1}}

です。物質量 Nの部分を質量に読み替えて、内部エネルギーの変化分をみると、

 \displaystyle
\varDelta U = 2CN(T_{\mathrm{mix}} - T_{\mathrm{rev}}) \simeq 7.78 \mathrm{kcal} \simeq 32.56 \mathrm{kJ}

が得られます。当たり前ですが、水2kgを約46.1℃から50℃にするエネルギーがそのまま仕事になっています。単純に混ぜた場合はその分のエネルギーを「無駄に」温度上昇に使ってしまったから不可逆になったとも言えます。

おわりに

なるべく簡単な例でエントロピーを扱おうとしたのですが、またそこそこ長い文量になってしまいました。可逆操作の理解に少しでも貢献できたら何よりです。

1kgずつ用意した100℃の水と0℃の水が、約46℃の水と約33kJの仕事になるという、普段はあまり考えない事実を熱力学が教えてくれました。

今回の例は、以下の本で扱われている題材を下敷きにしています。他の熱力学の教科書とはかなり毛色の違う本です。いずれ、この本の紹介をすることになると思います。

*1:定義域が気になる方は0℃から100℃の範囲に制限してください。

*2:セルシウス温度で平均を取りましたが、絶対温度とは定数がずれているだけなので、相加平均には影響がありません。

*3:ここでの温度は絶対温度で測る必要があります。

*4:田崎晴明『熱力学 現代的な視点から』 p.101

*5:ここでは水の温度上昇がわかりやすいように、あえてカロリーで計算します。

理想気体の基本関係式(エントロピー表示)の導出

はじめに

熱力学では熱力学変数の関係を状態方程式で表して,個々の系を表現します。状態方程式のとり方は様々ありますが,清水本[*1]や田崎本[*2],佐々本[*3]などで述べられているように,基本関係式(fundamental equations)ないし完全な熱力学関数(conplete thermodynamic function)と呼ばれる,特定の熱力学変数の組で関数を構成すると見通しが良くなることが知られています。

たとえば,内部エネルギー Uエントロピー S,体積 V,物質量 N で表す,

 \displaystyle
U = U(S, V, N)

は基本関係式になります。なぜなら,熱力学第一法則と熱力学第二法則を組み合わせて得られる微分形式

 \displaystyle
\mathrm{d}U = T \mathrm{d}S -p \mathrm{d}V + \mu \mathrm{d}N

から読み取れるように,温度 T,圧力 p,化学ポテンシャル \muの表式が U(S, V, N)偏微分から,

 \displaystyle
T = \left( \frac{\partial U}{\partial S} \right)_{V, N} , \quad 
p = -\left( \frac{\partial U}{\partial V} \right)_{S, N} , \quad
\mu = \left( \frac{\partial U}{\partial N} \right)_{S, V}

のように導けるからです。

基本関係式は,上で述べた内部エネルギー表示 U(S, V, N)の他に,エントロピー表示 S(U, V, N)ヘルムホルツの自由エネルギー表示 F(T, V, N),ギブスの自由エネルギー表示 G(T, p, N),エンタルピー表示 H(S, p, N)などがあります。 エントロピー表示を用いた場合は,対応する微分形式は

 \displaystyle
\mathrm{d}S = \frac{1}{T} \mathrm{d}U +\frac{p}{T} \mathrm{d}V - \frac{ \mu }{T} \mathrm{d}N

となり,これは先程の内部エネルギー表示での微分形式を移項して \mathrm{d}S について整理したものと見なせます*4

そこで,本記事では理想気体エントロピー基本関係式 S(U, V, N) *5

 \displaystyle
S(U, V, N) = \frac{N}{N_0} S_0 + RN \log \left [ \left( \frac{U}{U_0} \right) ^c \left( \frac{V}{V_0} \right) \left( \frac{N_0}{N} \right) ^{c+1} \right ]

 cは定数)を,おなじみの状態方程式

 \displaystyle
PV = NRT

内部エネルギーの式

 \displaystyle
U = cNRT

からなるべくシンプルに導出します。

変数の削減(単位物質量あたり)

まず,導出の前段階として,熱力学変数の示量性に注目して変数を削減します。示量性とは系のサイズを \lambda倍したときに,元のサイズの系の \lambda倍の物理量が得られる性質です。エントロピーを例に式にすると

 \displaystyle
\lambda S(U, V, N) = S(\lambda U, \lambda V, \lambda N)

のようになります。

ここでさらに \lambda=1/Nとすることで,

 \displaystyle
\frac{1}{N} S(U, V, N) = S(U/N, V/N, 1) = S(u, v, 1) := s(u, v)

と,単位物質量あたりのエントロピー s:=S/N,内部エネルギー u:=U/N,体積 v:=V/Nの関係式が得られます。 この式では物質量 Nを考えないで済むため,式の導出が簡潔に行なえます。微分形式では,

 \displaystyle
\mathrm{d}s = \frac{1}{T} \mathrm{d}u + \frac{p}{T} \mathrm{d}v

となります。元の式から,化学ポテンシャル \muをひとまず無視して進められるようになりました。

理想気体の状態方程式の代入

状態方程式を単位物質量あたりの関係に置き換えます。温度 Tや圧力 pは示強性の変数なので,そのままで良いことに注意すると,状態方程式 PV=NRTからは,

 \displaystyle
\frac{p}{T} = \frac{R}{v}

内部エネルギーの式 U=cNRTからは,

 \displaystyle
\frac{1}{T} = \frac{cR}{u}

が得られます。少し細工を加えてあるように,微分形式の係数がきれいに表されていることが見て取れます。

これらを単位物質量あたりのエントロピー微分形式に代入し,

 \displaystyle
\mathrm{d}s = \frac{cR}{u} \mathrm{d}u + \frac{R}{v} \mathrm{d}v

として,これを u, vについて積分することで,

 \displaystyle
s(u, v) = s_0 + cR \log \left( \frac{u}{u_0} \right) + R \log \left( \frac{v}{v_0} \right)

が得られます。ここで s_0, u_0, v_0は基準状態を表す定数です。 \logについても整理すれば,

 \displaystyle
s(u, v) = s_0 + R \log \left [ \left( \frac{u}{u_0} \right)^c \left( \frac{v}{v_0} \right) \right ]

となります。単位物質量あたりのエントロピーについての基本関係式が得られました。

最後に単位物質量あたりの物理量を元に戻します。途中で導入した定数 s_0, u_0, v_0も,

 \displaystyle
s_0 = S_0 / N_0, \quad
u_0 = U_0 / N_0, \quad
v_0 = V_0 / N_0

と置き直すことで,最初に述べたエントロピー表示の基本関係式

 \displaystyle
S(U, V, N) = \frac{N}{N_0} S_0 + RN \log \left [ \left( \frac{U}{U_0} \right) ^c \left( \frac{V}{V_0} \right) \left( \frac{N_0}{N} \right) ^{c+1} \right ]

が得られます。これらの導出を経て,式に \logが現れるのは状態方程式の変形でちょうど 1/u 1/v積分が現れるためであったこと, Nについての指数が -(c+1)なのは単純に U Vの示量性を確保するためであったと理解できます。

理想気体の化学ポテンシャル(おまけ)

エントロピー表示の基本関係式が得られたため,その偏微分から化学ポテンシャル \muの表式が計算できます。

 
\begin {align}
-\frac{\mu}{T} &= \left( \frac{\partial S}{\partial N} \right)_{U, V} \\
&= \frac{S_0}{N_0} + R \log \left [ \left( \frac{U}{U_0} \right) ^c \left( \frac{V}{V_0} \right) \left( \frac{N_0}{N} \right) ^{c+1} \right ] -(c+1)R \\
&= \frac{S}{N} -(c+1)R
\end {align}

最後の行では,第1項と第2項の和が,単純に S/Nとなっているため置き換えました。したがって,

 \displaystyle
\mu = T \left [ (c+1)R - \frac{S}{N} \right ]

が得られます。

実のところ,これは偏微分をしなくても得られます。系の示量性の制約から,一般的に

 \displaystyle
U = TS -pV + \mu N

が成立しなくてはならないためです(これは微分形式ではありません!)。理想気体の場合には,

 
\begin {align}
\mu N &= U -TS +pV \\
&= cNRT -TS +NRT \\
&= T [ (c+1)R -S ]
\end {align}

となり,偏微分で導いた表式と一致していることが分かります。

おわりに

理想気体エントロピー表示の基本関係式の導出を行いました。清水本では天下り的に与えられ,他の教科書でも主に S(T,V,N)の変数での扱いが中心なので,高校物理の知識とつなげるためにも直接の導出を試みました。 理想気体の状態方程式が,まるでパズルのピースがそこに嵌るかのようにエントロピー微分形式と適合しているのは気持ちが良いところです。なお,ここではスルーしましたが熱力学的絶対温度理想気体温度が一致することは熱力学第二法則での議論を行わないと示せないため,それらが済んだあとの導出ということになります。

数式記述の練習も兼ねていたのですが,思いのほか長くなってしまい良い練習となりました。

今後も熱力学関連で記事を書いていけたらと思います。

*1:清水明『熱力学の基礎』 東京大学出版会

*2:田崎晴明『熱力学 現代的な視点から』 培風館

*3:佐々真一『熱力学入門』 共立出版

*4:実際は合成関数の偏微分でのチェーンルールが自然と背後で行われていて,整合性を保っているのが微分形式の素晴らしいところです。

*5:清水本の第1版(緑の方)の p. 113