def predict(device, in_data, out_data, model, loss_func, batchsize, additional_conditions={}): x_data = in_data y_data = out_data # データ数を確認 n_samples_ev = len(x_data) # 入力データタイプの確認 if type(x_data[0]) == str: # 画像の場合は画像サイズ・チャンネル数の情報を取得しておく x_type_str = True x_channels, x_height, x_width = load_single_image(x_data[0]).shape x_size = None if 'input_scale' in additional_conditions: x_width = round(x_width * additional_conditions['input_scale']) x_height = round(x_height * additional_conditions['input_scale']) x_size = (x_width, x_height) if 'in_channels' in additional_conditions: x_channels = additional_conditions['in_channels'] x_color_mode = 0 if x_channels == 1 else 1 else: # 数値の場合は numpy.ndarray に変換しておく x_type_str = False x_data = to_nparray(x_data) # 出力データタイプも同様にして確認 if type(y_data[0]) == str: y_type_str = True y_channels, y_height, y_width = load_single_image(y_data[0]).shape y_size = None if 'output_scale' in additional_conditions: y_width = round(y_width * additional_conditions['output_scale']) y_height = round(y_height * additional_conditions['output_scale']) y_size = (y_width, y_height) if 'out_channels' in additional_conditions: y_channels = additional_conditions['out_channels'] y_color_mode = 0 if y_channels == 1 else 1 else: y_type_str = False y_data = to_nparray(y_data) # 追加情報の確認 x_with_noise = False y_with_noise = False x_noise_points = 0 y_noise_points = 0 if 'input_with_noise' in additional_conditions: x_with_noise = True x_noise_points = additional_conditions['input_with_noise'] if 'output_with_noise' in additional_conditions: y_with_noise = True y_noise_points = additional_conditions['output_with_noise'] # モデルをGPU上に移動 model = model.to(device) model.eval() # 評価用データを用いて損失を計算・表示 n_input = 0 n_failed = 0 sum_loss = 0 perm = np.arange(0, n_samples_ev) for i in range(0, n_samples_ev, batchsize): # ミニバッチ(入力側)を作成 if x_type_str: x = torch.tensor(load_images(x_data, ids=perm[i:i + batchsize], size=x_size, with_noise=x_with_noise, mode=x_color_mode), device=device) elif x_data.dtype == np.int32: x = torch.tensor(x_data[i:i + batchsize], device=device, dtype=torch.long) else: x = torch.tensor(x_data[i:i + batchsize], device=device) # ミニバッチ(出力側)を作成 calc_accuracy = False if y_type_str: y = torch.tensor(load_images(y_data, ids=perm[i:i + batchsize], size=y_size, with_noise=y_with_noise, mode=y_color_mode), device=device) elif y_data.dtype == np.int32: y = torch.tensor(y_data[i:i + batchsize], device=device, dtype=torch.long) calc_accuracy = True else: y = torch.tensor(y_data[i:i + batchsize], device=device) z = model(x) loss = loss_func(z, y) sum_loss += float(loss) * len(x) n_input += len(x) if calc_accuracy: y_cpu = y.to('cpu').detach().numpy().copy() z_cpu = z.to('cpu').detach().numpy().copy() n_failed += np.count_nonzero(np.argmax(z_cpu, axis=1) - y_cpu) del y_cpu del z_cpu del loss del z del y del x print('test loss = {0:.6f}'.format(sum_loss / n_input), file=sys.stderr) if calc_accuracy: acc = (n_samples_ev - n_failed) / n_samples_ev print('accuracy = {0:.2f}%'.format(100 * acc), file=sys.stderr) print('', file=sys.stderr) model.to('cpu')
def train(device, model_dir, in_data, out_data, model, loss_func, batchsize, epochs, ratio=0.1, stepsize=1, additional_conditions={}): # データセットを分割 x_train, x_valid, y_train, y_valid = split(in_data, out_data, ratio) # データ数を確認 n_samples = len(x_train) n_samples_ev = len(x_valid) # 入力データタイプの確認 if type(x_train[0]) == str: # 画像の場合は画像サイズ・チャンネル数の情報を取得しておく x_type_str = True x_channels, x_height, x_width = load_single_image(x_train[0]).shape x_size = None if 'input_scale' in additional_conditions: x_width = round(x_width * additional_conditions['input_scale']) x_height = round(x_height * additional_conditions['input_scale']) x_size = (x_width, x_height) if 'in_channels' in additional_conditions: x_channels = additional_conditions['in_channels'] x_color_mode = 0 if x_channels == 1 else 1 else: # 数値の場合は numpy.ndarray に変換しておく x_type_str = False x_train = to_nparray(x_train) x_valid = to_nparray(x_valid) # 出力データタイプも同様にして確認 if type(y_train[0]) == str: y_type_str = True y_channels, y_height, y_width = load_single_image(y_train[0]).shape y_size = None if 'output_scale' in additional_conditions: y_width = round(y_width * additional_conditions['output_scale']) y_height = round(y_height * additional_conditions['output_scale']) y_size = (y_width, y_height) if 'out_channels' in additional_conditions: y_channels = additional_conditions['out_channels'] y_color_mode = 0 if y_channels == 1 else 1 else: y_type_str = False y_train = to_nparray(y_train) y_valid = to_nparray(y_valid) # 追加情報の確認 x_with_noise = False y_with_noise = False x_noise_points = 0 y_noise_points = 0 if 'input_with_noise' in additional_conditions: x_with_noise = True x_noise_points = additional_conditions['input_with_noise'] if 'output_with_noise' in additional_conditions: y_with_noise = True y_noise_points = additional_conditions['output_with_noise'] # モデルをGPU上に移動 model = model.to(device) # オプティマイザーの用意 optimizer = optim.Adam(model.parameters()) # 学習処理ループ for e in range(epochs): # 現在のエポック番号を表示 print('Epoch {0}'.format(e + 1), file=sys.stderr) # 損失関数の値が小さくなるようにモデルパラメータを更新 model.train() n_input = 0 sum_loss = 0 perm = np.random.permutation(n_samples) for i in range(0, n_samples, batchsize * stepsize): model.zero_grad() # ミニバッチ(入力側)を作成 if x_type_str: x = torch.tensor(load_images(x_train, ids=perm[i:i + batchsize], size=x_size, with_noise=x_with_noise, n_noise_points=x_noise_points, mode=x_color_mode), device=device) elif x_train.dtype == np.int32: x = torch.tensor(x_train[perm[i:i + batchsize]], device=device, dtype=torch.long) else: x = torch.tensor(x_train[perm[i:i + batchsize]], device=device) # ミニバッチ(出力側)を作成 if y_type_str: y = torch.tensor(load_images(y_train, ids=perm[i:i + batchsize], size=y_size, with_noise=y_with_noise, n_noise_points=y_noise_points, mode=y_color_mode), device=device) elif y_train.dtype == np.int32: y = torch.tensor(y_train[perm[i:i + batchsize]], device=device, dtype=torch.long) else: y = torch.tensor(y_train[perm[i:i + batchsize]], device=device) loss = loss_func(model(x), y) loss.backward() optimizer.step() sum_loss += float(loss) * len(x) n_input += len(x) del loss del y del x # 損失関数の現在値を表示 print(' train loss = {0:.6f}'.format(sum_loss / n_input), file=sys.stderr) # 検証用データを用いた場合の損失を計算・表示 model.eval() n_input = 0 n_failed = 0 sum_loss = 0 perm = np.arange(0, n_samples_ev) for i in range(0, n_samples_ev, batchsize): # ミニバッチ(入力側)を作成 if x_type_str: x = torch.tensor(load_images(x_valid, ids=perm[i:i + batchsize], size=x_size, with_noise=x_with_noise, n_noise_points=x_noise_points, mode=x_color_mode), device=device) elif x_valid.dtype == np.int32: x = torch.tensor(x_valid[i:i + batchsize], device=device, dtype=torch.long) else: x = torch.tensor(x_valid[i:i + batchsize], device=device) # ミニバッチ(出力側)を作成 calc_accuracy = False if y_type_str: y = torch.tensor(load_images(y_valid, ids=perm[i:i + batchsize], size=y_size, with_noise=y_with_noise, n_noise_points=y_noise_points, mode=y_color_mode), device=device) elif y_valid.dtype == np.int32: y = torch.tensor(y_valid[i:i + batchsize], device=device, dtype=torch.long) calc_accuracy = True else: y = torch.tensor(y_valid[i:i + batchsize], device=device) z = model(x) loss = loss_func(z, y) sum_loss += float(loss) * len(x) n_input += len(x) if calc_accuracy: y_cpu = y.to('cpu').detach().numpy().copy() z_cpu = z.to('cpu').detach().numpy().copy() n_failed += np.count_nonzero(np.argmax(z_cpu, axis=1) - y_cpu) del y_cpu del z_cpu if y_type_str and i == 0: if e == 0: x_cpu = x.to('cpu').detach().numpy().copy() y_cpu = y.to('cpu').detach().numpy().copy() save_progress(model_dir + 'input.png', x_cpu, n_data_max=25, n_data_per_row=5, mode=x_color_mode) save_progress(model_dir + 'ground_truth.png', y_cpu, n_data_max=25, n_data_per_row=5, mode=y_color_mode) del x_cpu del y_cpu z_cpu = z.to('cpu').detach().numpy().copy() save_progress(model_dir + 'output_ep{0}.png'.format(e + 1), z_cpu, n_data_max=25, n_data_per_row=5, mode=y_color_mode) del z_cpu del loss del z del y del x print(' valid loss = {0:.6f}'.format(sum_loss / n_input), file=sys.stderr) if calc_accuracy: acc = (n_samples_ev - n_failed) / n_samples_ev print(' accuracy = {0:.2f}%'.format(100 * acc), file=sys.stderr) print('', file=sys.stderr) return model.to('cpu')
print('output file: {0}'.format(out_filepath), file=sys.stderr) print('model file: {0}'.format(model_filepath), file=sys.stderr) print('', file=sys.stderr) # 画像の縦幅・横幅・チャンネル数の設定 width = 128 # VGGFace2顔画像の場合,横幅は 128 pixels height = 128 # VGGFace2顔画像の場合,縦幅も 128 pixels # カラー化オートエンコーダをロード model = myColorizationAE(width, height) model.load_state_dict(torch.load(model_filepath)) model = model.to(dev) model.eval() # 処理の実行 img = np.asarray([load_single_image(in_filepath, mode=0)]) # mode=0: 入力ファイルをグレースケール画像として読み込む show_image(img[0], title='input image', mode=0) # 入力画像を表示 x = torch.tensor(img, device=dev) y = model(x) y_cpu = y.to('cpu').detach().numpy().copy() del y del x # 結果を保存 show_image(y_cpu[0], title='output image', mode=1) # カラー化結果を表示 y_cpu = np.asarray(y_cpu[0].transpose(1, 2, 0) * 255, dtype=np.uint8) cv2.imwrite(out_filepath, y_cpu) del y_cpu print('', file=sys.stderr)
# 画像の縦幅・横幅・チャンネル数の設定 width = 128 # VGGFace2顔画像の場合,横幅は 128 pixels height = 128 # VGGFace2顔画像の場合,縦幅も 128 pixels channels = 3 # VGGFace2顔画像はカラー画像なので,チャンネル数は 3 color_mode = 0 if channels == 1 else 1 in_size = (width // 2, height // 2) # アップサンプリング用オートエンコーダをロード model = myUpSamplingAE(width, height, channels) model.load_state_dict(torch.load(model_filepath)) model = model.to(dev) model.eval() # 処理の実行 img = np.asarray( [load_single_image(in_filepath, size=in_size, mode=color_mode)]) # 入力画像をにリサイズして読み込む show_image(img[0], title='input image', mode=color_mode) # 入力画像を表示 x = torch.tensor(img, device=dev) y = model(x) y_cpu = y.to('cpu').detach().numpy().copy() del y del x # 結果を保存 show_image(y_cpu[0], title='output image', mode=color_mode) # アップサンプリング結果を表示 y_cpu = np.asarray(y_cpu[0].transpose(1, 2, 0) * 255, dtype=np.uint8) cv2.imwrite(out_filepath, y_cpu) del y_cpu print('', file=sys.stderr)
print('device: {0}'.format(dev_str), file=sys.stderr) print('input file: {0}'.format(in_filepath), file=sys.stderr) print('output file: {0}'.format(out_filepath), file=sys.stderr) print('model file: {0}'.format(model_filepath), file=sys.stderr) print('', file=sys.stderr) # 学習済みのオートエンコーダをロード cnn = myDenoisingAE(WIDTH, HEIGHT, CHANNELS) cnn.load_state_dict(torch.load(model_filepath)) # 入力画像のカラーモードを設定 color_mode = 0 if CHANNELS == 1 else 1 # 入力画像にごま塩ノイズを付加して読み込む img = load_single_image(in_filepath, mode=color_mode, with_noise=True, n_noise_points=100) # 100点分のごま塩ノイズを付加 # 入力画像を表示 show_image(img, title='input image', mode=color_mode) # 入力画像をモデルに入力してノイズ除去 y = predict_once(device=dev, model=cnn, in_data=img) # ノイズ除去結果を表示 show_image(y, title='output image', mode=color_mode) # ノイズ除去結果をファイルに保存 y = np.asarray(y.transpose(1, 2, 0) * 255, dtype=np.uint8) cv2.imwrite(out_filepath, y)
channels = 1 # MNIST文字画像はグレースケール画像なので,チャンネル数は 1 color_mode = 0 if channels == 1 else 1 # 圧縮/復元に用いるオートエンコーダをロード model = myAutoEncoder(width, height, channels, dimension) model.load_state_dict(torch.load(model_filepath)) model = model.to(dev) model.eval() # 処理の実行 if mode == 'compression': ### 圧縮モード ### # 画像を読み込む img = np.asarray([load_single_image(in_filepath, mode=color_mode)]) # 入力画像を読み込む show_image(img[0], title='input image', mode=color_mode) # 入力画像を表示 # 圧縮 x = torch.tensor(img, device=dev) y = model.encode(x) y_cpu = y.to('cpu').detach().numpy().copy() del y del x # 結果を保存 with open(out_filepath, 'w') as f: for i in range(y_cpu.shape[1]): print(y_cpu[0, i], file=f) del y_cpu
print('', file=sys.stderr) # 学習済みのオートエンコーダをロード cnn = myAutoEncoder(WIDTH, HEIGHT, CHANNELS, dimension) cnn.load_state_dict(torch.load(model_filepath)) # 画像のカラーモードを設定 color_mode = 0 if CHANNELS == 1 else 1 # 処理の実行 if mode == 'compression': ### 圧縮モード ### # 入力画像を読み込む img = load_single_image(in_filepath, mode=color_mode) # 入力画像を表示 show_image(img, title='input image', mode=color_mode) # 入力画像をモデルに入力して圧縮 y = predict_once(device=dev, model=cnn, in_data=img, module='encode') # 圧縮結果をファイルに保存 with open(out_filepath, 'w') as f: for i in range(len(y)): print(y[i], file=f) else: ### 復元モード ###
print('device: {0}'.format(dev_str), file=sys.stderr) print('input file: {0}'.format(in_filepath), file=sys.stderr) print('output file: {0}'.format(out_filepath), file=sys.stderr) print('model file: {0}'.format(model_filepath), file=sys.stderr) print('', file=sys.stderr) # 学習済みのオートエンコーダをロード(本来のVGGFace2顔画像を縦横半分にしたものを入力画像として用いるので,WIDTH と HEIGHT を 2 で割る) cnn = myUpSamplingAE(WIDTH // 2, HEIGHT // 2, CHANNELS) cnn.load_state_dict(torch.load(model_filepath)) # 入力画像のカラーモードを設定 color_mode = 0 if CHANNELS == 1 else 1 # 入力画像を縦横半分にリサイズして読み込む img = load_single_image(in_filepath, size=(WIDTH // 2, HEIGHT // 2), mode=color_mode) # 入力画像を表示 show_image(img, title='input image', mode=color_mode) # 入力画像をモデルに入力してアップサンプリング y = predict_once(device=dev, model=cnn, in_data=img) # アップサンプリング結果を表示 show_image(y, title='output image', mode=color_mode) # アップサンプリング結果をファイルに保存 y = np.asarray(y.transpose(1, 2, 0) * 255, dtype=np.uint8) cv2.imwrite(out_filepath, y)
# オプション情報の設定・表示 in_filepath = args.in_filepath # 入力ファイルパス out_filepath = args.out_filepath # 出力ファイルパス model_filepath = args.model # 学習済みモデルのファイルパス print('device: {0}'.format(dev_str), file=sys.stderr) print('input file: {0}'.format(in_filepath), file=sys.stderr) print('output file: {0}'.format(out_filepath), file=sys.stderr) print('model file: {0}'.format(model_filepath), file=sys.stderr) print('', file=sys.stderr) # 学習済みのオートエンコーダをロード cnn = myColorizationAE(WIDTH, HEIGHT) cnn.load_state_dict(torch.load(model_filepath)) # mode=0: 入力ファイルをグレースケール画像として読み込む img = load_single_image(in_filepath, mode=0) # 入力画像を表示 show_image(img, title='input image', mode=0) # 入力画像をモデルに入力してカラー化 y = predict_once(device=dev, model=cnn, in_data=img) # カラー化結果を表示 show_image(y, title='output image', mode=1) # カラー化結果をファイルに保存 y = np.asarray(y.transpose(1, 2, 0) * 255, dtype=np.uint8) cv2.imwrite(out_filepath, y) print('', file=sys.stderr)