Google Colabで数式書いてからQiitaに投稿するのめんどくさい話

私は、Google ColabやJupyter Notebook等でQiitaに投稿する記事の下書きを書いておくタイプ。

コードと説明文だけの記事であれば比較的簡単に転載できるのだけど、数式が大量にある場合、Google Colabで採用されているLaTeXからQiitaで使えるMathJaxの記法に一部変更する必要があったり。

その転載時に使えそうな超簡単なコードをPythonでパパっと書いてみる、という記事。

LaTeXやMathJaxの文法についてはQiitaをはじめとする、様々なところで情報共有がされているので、それについてはざっくり省略。

早速コードを。

```
import re
import tkinter as tk


root = tk.Tk()
root.geometry("700x300")

entry = tk.Text(bg="#fff", fg="#000", height=18, width=90)

entry.place(x=90, y=70)
entry.pack()

button = tk.Button(text="変換")
button.place(x=345, y=270)

def click():
    lines = entry.get("1.0", "end")
    transformed = transform(lines)

button["command"] = click    #関数と関連付ける

# root.mainloop()の下に書くと認識されないっぽい
def transform(lines):
    line_list = lines.split('\n')
    pattern = re.compile(r'\$\$')
    head = False
    for line in lines.split('\n'):
        match = bool(pattern.search(line))
        if match:
            head = not head
            # 奇数回目の$$は```mathで置き換える。
            # 偶数回目の$$は```で置き換える。
            quote = "```math" if head else "```"
            print(pattern.sub(quote, line))
        else:
            print(line)
    return lines

root.mainloop()
```


今回はtkinterを用いて文字入力用のテキストボックスを作成した。tkinterについてはほとんど触ったことが無いので、だいぶてきとうなコーディング。

このコードを.pyファイルとして保存し、実行するとテキストボックスが出てくる。入力後に'変換'ボタンを押下すると、標準出力として変換後の文字列たちが表示されるプログラム。

記法の変換をしている部分は、transform関数のところ。ただただ、

・奇数番目の $$ は ```math で置き換える

・偶数番目の $$ は ``` で置き換える

を実施しているだけ。実は$$のままでも数式は表示できるが、式の改行ができなかったり色々問題があるのですべて置き換えることにする。

ただ、

\`\`\`math の前に空白行がある必要があったり、```の後に空白行を入れる必要があったり、色々なルールがある。

なので、たとえば

(改行)

$$

数式

$$

(改行)

という書式スタイルを普段から行っていれば、本プログラムで変換した後は、

(改行)

\```math

数式

\```

(改行)

となって、MathJaxでの表示が問題なくできる。言葉で説明するの難しい。。

実際にやってみよう。

![スクリーンショット (586).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237351/521b19dd-55d7-6c39-36d4-44d27b9db277.png)

上記は、私が途中まで書いたまま放置した、数学の記事だ。数式がいろいろ出てくる。

LaTeX的にはこれをどう書いているのか。

```
### ベイズ線形回帰モデル

ベイズ線形回帰モデルは、入力値 $ \textbf{x} \in \mathbb{R}^M $、パラメータ $ \textbf{a} \in \mathbb{R}^M $、出力値 $ y_n \in \mathbb{R} $、ノイズ $ ϵ \in \mathbb{R} $ を用いて以下で表される。

$$
y_n = \textbf{a}^T \textbf{x} + ε
$$

ノイズ $ ε $ は分散 $ σ^2 $ の1次元ガウス分布に従うとする。

$$
\begin{eqnarray*}
p(ε|σ^2)
&=& Norm_1(ε|0, σ^2) \\
&=& \frac{exp(-\frac{ε^2}{2 σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
$$

このモデルでは、パラメータをまとめて $ \textbf{ω} = (\textbf{a}, σ^2) $ と表現することとする。

$$
ε = y - \textbf{a}^T \textbf{x}
$$

より、尤度関数は次のようになる。

$$
\begin{eqnarray*}
p(y|\textbf{x}, \textbf{ω})
&=& Norm_1(y|\textbf{a}^T \textbf{x}, σ^2) \\
&=& \frac{exp(\frac{(y - \textbf{a}^T \textbf{x})^2}{2σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
$$
```

コードっぽくて見づらいかもしれないが、上記がLaTeXでの記法である。$$に関しては、MathJaxの記法である\```mathに書き換えてもそのまま表示できるよう、改行には気を付けている。

さて、この文字を冒頭に示したプログラムに突っ込んでみよう。

結果は以下である。ただし、以下は、出力結果の中のバッククオートを勝手に手動でシングルクオートに書き換えたものである。バッククオートのままだと、まとめてコードっぽく表示させる際にいろいろ問題があるので、、、

```

### ベイズ線形回帰モデル

ベイズ線形回帰モデルは、入力値 $ \textbf{x} \in \mathbb{R}^M $、パラメータ $ \textbf{a} \in \mathbb{R}^M $、出力値 $ y_n \in \mathbb{R} $、ノイズ $ ϵ \in \mathbb{R} $ を用いて以下で表される。

'''math
y_n = \textbf{a}^T \textbf{x} + ε
'''

ノイズ $ ε $ は分散 $ σ^2 $ の1次元ガウス分布に従うとする。

'''math
\begin{eqnarray*}
p(ε|σ^2)
&=& Norm_1(ε|0, σ^2) \\
&=& \frac{exp(-\frac{ε^2}{2 σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
'''

このモデルでは、パラメータをまとめて $ \textbf{ω} = (\textbf{a}, σ^2) $ と表現することとする。

'''math
ε = y - \textbf{a}^T \textbf{x}
'''

より、尤度関数は次のようになる。

'''math
\begin{eqnarray*}
p(y|\textbf{x}, \textbf{ω})
&=& Norm_1(y|\textbf{a}^T \textbf{x}, σ^2) \\
&=& \frac{exp(\frac{(y - \textbf{a}^T \textbf{x})^2}{2σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
'''

```

これだけみても、「はいはい置換できましたね、、、」という感じか。実際にQiita上でそれぞれをエスケープせずに表示させてみよう。

オリジナル：

### ベイズ線形回帰モデル

ベイズ線形回帰モデルは、入力値 $ \textbf{x} \in \mathbb{R}^M $、パラメータ $ \textbf{a} \in \mathbb{R}^M $、出力値 $ y_n \in \mathbb{R} $、ノイズ $ ϵ \in \mathbb{R} $ を用いて以下で表される。

$$
y_n = \textbf{a}^T \textbf{x} + ε
$$

ノイズ $ ε $ は分散 $ σ^2 $ の1次元ガウス分布に従うとする。

$$
\begin{eqnarray*}
p(ε|σ^2)
&=& Norm_1(ε|0, σ^2) \\
&=& \frac{exp(-\frac{ε^2}{2 σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
$$

このモデルでは、パラメータをまとめて $ \textbf{ω} = (\textbf{a}, σ^2) $ と表現することとする。

$$
ε = y - \textbf{a}^T \textbf{x}
$$

より、尤度関数は次のようになる。

$$
\begin{eqnarray*}
p(y|\textbf{x}, \textbf{ω})
&=& Norm_1(y|\textbf{a}^T \textbf{x}, σ^2) \\
&=& \frac{exp(\frac{(y - \textbf{a}^T \textbf{x})^2}{2σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
$$


置換後：

### ベイズ線形回帰モデル

ベイズ線形回帰モデルは、入力値 $ \textbf{x} \in \mathbb{R}^M $、パラメータ $ \textbf{a} \in \mathbb{R}^M $、出力値 $ y_n \in \mathbb{R} $、ノイズ $ ϵ \in \mathbb{R} $ を用いて以下で表される。

```math
y_n = \textbf{a}^T \textbf{x} + ε
```

ノイズ $ ε $ は分散 $ σ^2 $ の1次元ガウス分布に従うとする。

```math
\begin{eqnarray*}
p(ε|σ^2)
&=& Norm_1(ε|0, σ^2) \\
&=& \frac{exp(-\frac{ε^2}{2 σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
```

このモデルでは、パラメータをまとめて $ \textbf{ω} = (\textbf{a}, σ^2) $ と表現することとする。

```math
ε = y - \textbf{a}^T \textbf{x}
```

より、尤度関数は次のようになる。

```math
\begin{eqnarray*}
p(y|\textbf{x}, \textbf{ω})
&=& Norm_1(y|\textbf{a}^T \textbf{x}, σ^2) \\
&=& \frac{exp(\frac{(y - \textbf{a}^T \textbf{x})^2}{2σ^2})}{\sqrt{2 \pi σ^2}} \\
\end{eqnarray*}
```

この例だと数式の改行の必要性も微妙で、あまりありがたみを感じないかもしれないが、数式ばっかりの記事を書く人がいるとしたら、もしかしたら役に立つかもしれない、、、