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

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

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

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

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

前項の方法で誘電体分布をランダムに変えて計算し、
多数の誘電体分布と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-1に学習部のソースコードを示します。
ユーザーの行う作業は以下の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() # 最適化関数更新
ニューラルネットワークモデルには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=複素数)