目次

2. 計算手法

2.1 処理の流れ

図2-1に処理の流れを示します。
以下の三つの部分から成ります。

  1. 教師データ作成: 多数の誘電率分布を作成し、FDTD法によりS行列を計算します。
  2. 学習: 深層学習により教師データを学習し、最適化されたパラメーターファイルファイルを得ます。
  3. 推論: パラメーターファイルファイルを用いてS行列測定値から誘電率分布を推定します。


図2-1 処理の流れ

2.2 FDTD法

2.2.1 FDTD法の計算モデル

図2-2にFDTD法の計算モデルを示します。
誘電体を含む対象領域を考え、その外部に送信アンテナと受信アンテナを置きます。 それらを含む領域がFDTD法の計算領域となり、計算領域の電界分布が計算されます。
なお、送信アンテナの数と受信アンテナの数は一般的に同じとします。
3次元モデルではZ方向について同様に考えます。アンテナの配置については後述します。


図2-2 FDTD法の計算モデル(2次元モデル)

図2-3に送信アンテナを移動させたときの電界分布を示します。
この例では送信アンテナの数は16です。 図中の赤い点が送信アンテナであり、黒い線が誘電体です。
送信アンテナを移動させると電界分布が変わります。 誘電体は電界を集める効果があります。


図2-3 電界分布(送信アンテナ数=16)

2.2.2 S行列

FDTD法では一つの送信アンテナを給電すると、 すべての受信アンテナの電界を一度に求めることができます。
したがって図2-3の計算から図2-4のようなS行列が得られます。
ここで横軸は送信アンテナ、縦軸は受信アンテナです。
S行列は誘電率分布の情報を持っています。


図2-4 S行列(送信アンテナ数=受信アンテナ数=16)

2.2.3 順問題と逆問題の関係

図2-5に順問題と逆問題の関係を示します。
上で述べた方法により誘電率分布からS行列を求めることが順問題です。
逆にS行列から誘電率分布を求めることが逆問題であり、本プログラムの目的です。


図2-5 順問題と逆問題の関係

2.3 深層学習

2.3.1 ニューラルネットワーク

前項の方法で誘電体分布をランダムに変えて計算し、 多数の誘電体分布とS行列画像の組(教師データ)を求めます。
そのデータを用いて深層学習を行い、地中レーダー画像から誘電率分布を推定することを考えます。
深層学習にはCNN(畳み込みニューラルネットワーク)を用います。
ネットワークの入力はS行列、 出力は式(2-1)(2D)または式(2-2)(3D)の損失(MSELoss)です。

 (2-1)
 (2-2)
 (2-3)
 (2-4)

ここで、(Mx, My, Mz)は対象領域のセル数、 εrtrueは正解(教師データ)の複素比誘電率、 εrpredは予測値の複素比誘電率です。
以下では、"損失(loss)"は式(2-4)とします。 これは複素比誘電率の予測誤差の平均値を表します。

2.3.2 学習部

リスト2-1に学習部のソースコードを示します。
ユーザーの行う作業は以下の2点です。

  1. S行列と誘電率分布の教師データをdatasetに代入する ※1
  2. モデル(ニューラルネットワーク)を定義する ※2
その他は深層学習共通のコードです。

リスト2-1 学習部のソースコード(PyTorch)


dataset設定      ※1
dataloader設定
model設定        ※2
criterion = nn.MSELoss()                      # 損失関数: MSE
optimizer = optim.Adam(model.parameters())    # 最適化関数: Adam
for epoch in range(num_epochs):               # エポックに関するループ
    for data, target in train_loader:         # ミニバッチに関するループ
        optimizer.zero_grad()                 # 勾配初期化
        output = model(data)                  # 順伝搬
        loss = criterion(output, target)      # 損失計算
        loss.backward()                       # 逆伝搬
        optimizer.step()                      # 最適化関数更新

2.3.3 ResNet

ニューラルネットワークモデルにはResNet[4][5]を使用します。
ResNet18,ResNet34,ResNet50を考えます。
モデルを定義する方法は以下の通りです。
ゼロから(ランダムな初期値から)学習するには以下のいずれかになります。

model = models.resnet18(weights=None)
model = models.resnet34(weights=None)
model = models.resnet50(weights=None)
最適化されたパラメーターからファインチューニングするには以下のいずれかになります。
model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
model = models.resnet34(weights=models.ResNet34_Weights.DEFAULT)
model = models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
ここでは前者を「重みなし」、後者を「重みあり」と呼びます。
その後、以下のように入力サイズと出力サイズを変更します。
model.conv1 = nn.Conv2d(入力チャネル, 64, 7, stride=2, padding=3, bias=False)
model.fc = nn.Linear(model.fc.in_features, 出力サイズ)
入力チャネル = S行列成分数(1/2) * 周波数数  (1=実数, 2=複素数)
出力サイズ = 誘電率推定数 = 2 * Nx * Ly (2D), 2 * Nx * Ny * Lz (3D)  (2は誘電率の実部と虚部を表す)