tf.image.non_max_suppression(
    boxes,
    scores,
    max_output_size,
    iou_threshold=0.5,
    score_threshold=float('-inf'),
    name=None
)

NMS라고 불리우는 함수이며, 모델이 예측한 bbox중 겹치는 부분이 많은 것들을 제거한다.

다음과 같은 과정을 거친다

1. 가장 높은 Score를 가진 순대로 내림차순한다.

2. 선택된 bbox와 나머지 bbox의 IOU를 계산한다. 이때, IOU threshold(보통 0.5)이상이면 제거해준다.

3. 객체당 하나의 bbox가 남거나 더 이상 계산할 bbox가 없을 때까지 위의 과정을 반복하게 된다.

아래가 non_max_suppression의 구현이다.

import numpy as np

def non_max_suppression(boxes, overlapThresh):
    if(len(boxes) == 0):
        raise ValueError('nonono')
        
    picked_class = []
    
    x1 = boxes[:, 0]
    y1 = boxes[:, 1]
    x2 = boxes[:, 2]
    y2 = boxes[:, 3]
    
    area = (x2 - x1 + 1) * (y2 - y1 + 1)
    idxs = np.argsort(y2)
    print(idxs)
    
    pick = []
    
    while len(idxs) > 0:
        # grab the last index in the indexes list and add the
        # index value to the list of picked indexes
        last = len(idxs) - 1
        i = idxs[last]
        print(last, i)
        pick.append(i)

        # find the largest (x, y) coordinates for the start of
        # the bounding box and the smallest (x, y) coordinates
        # for the end of the bounding box
        xx1 = np.maximum(x1[i], x1[idxs[:last]])
        yy1 = np.maximum(y1[i], y1[idxs[:last]])
        xx2 = np.minimum(x2[i], x2[idxs[:last]])
        yy2 = np.minimum(y2[i], y2[idxs[:last]])

        # compute the width and height of the bounding box
        w = np.maximum(0, xx2 - xx1 + 1)
        h = np.maximum(0, yy2 - yy1 + 1)

        # compute the ratio of overlap
        overlap = (w * h) / area[idxs[:last]]
        print('overlap : ',overlap)

        # delete all indexes from the index list that have
        idxs = np.delete(idxs, np.concatenate(([last],
            np.where(overlap > overlapThresh)[0])))
        
        print('idx : ', idxs)

        # return only the bounding boxes that were picked using the
        # integer data type
    return boxes[pick].astype("int")

출처 : https://www.pyimagesearch.com/2015/02/16/faster-non-maximum-suppression-python/

 

(Faster) Non-Maximum Suppression in Python - PyImageSearch

Non-maximum suppression is crucial for HOG + Linear SVM object detection systems. Learn how to obtain a 100x speedup when applying non-maximum suppression.

www.pyimagesearch.com

 

tf.boolean_mask(tensor, mask, name, axis)

1D-tensor
2D-tensor

 

Abstract

This paper introduces a deep-learning approach to photographic style transfer that handles a large variety of image content while faithfully transferring the reference style. Our approach builds upon the recent work on painterly transfer that separates style from the content of an image by considering different layers of a neural network. However, as is, this approach is not suitable for photorealistic style transfer. Even when both the input and reference images are photographs, the output still exhibits distortions reminiscent of a painting. Our contribution is to constrain the transformation from the input to the output to be locally affine in colorspace, and to express this constraint as a custom fully differentiable energy term. We show that this approach successfully suppresses distortion and yields satisfying photorealistic style transfers in a broad variety of scenarios, including transfer of the time of day, weather, season, and artistic edits.


이 논문은 다양한 이미지를 다루면서 reference style을 정확히 변형하는 deep-learning기반의 style transfer를 소개한다.

우리의 접근방식은 신경망의 서로 다른 층을 고려함으로써 이미지의 내용과 스타일을 구분하는 화가적 transfer에 관한 최근 연구에 기초한다.

그러나 이 방법은 포토리얼리즘(사물을 사진처럼 정확하고 상세하게 묘사하는 기법) style transfer에는 적절하지 않은 방법이다.

input과 reference image가 사진으로 주어질 때 여전히 output은 그림처럼 묘사되어 진다.

우리는 input이 output으로 변환되어질 때 colorspace에 affine을 locally하게 하도록 제약하고, 이러한 제약을 완전히 다른 energy term으로 표현했다.

이러한 방법은 왜곡을 성공적으로 억제하였고, the time of day(저녁, 아침 등), 날씨, 계절, 여러 예술적 요소들에 대한 transfer을 포함하여 다양한 이미지를 포토리얼리즘 스타일로 잘 변형하였다.


요약

  • 내 생각으로 이 논문의 전부는 밑의 loss_function인 것 같다.
  • 기존 논문들의 결과도 좋았지만 대체적으로 하늘에 빌딩건물 색이 칠해져 있다던지 하는 문제점이 많았는데, 종합적으로 더해서 이들을 loss function으로 제한했더니 잘 되더라!

 

Reference

Luan, F., Paris, S., Shechtman, E., & Bala, K. (2017). Deep photo style transfer. In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (pp. 4990-4998).

이글은 다음 문서를 참조합니다.

www.tensorflow.org/guide/keras/save_and_serialize

(번역은 자력 + 파파고 + 구글 번역기를 사용하였으니, 부자연스럽더라도 양해바랍니다.)


이번 가이드는 모델을 저장하는 방법과 serialization하는 방법을 다룹니다.

 

Part 1 : Saving Sequential models or Functional models

예제를 보곘습니다.

from tensorflow import keras
from tensorflow.keras import layers

inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)

model = keras.Model(inputs=inputs, outputs=outputs, name='3_layer_mlp')
model.summary()

훈련시킨 후 모델의 가중치와 optimizer state를 저장할 수 있습니다. 재미는 없지만 학습하지 않은 모델도 저장 가능합니다.

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

model.compile(loss='sparse_categorical_crossentropy',
              optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train,
                    batch_size=64,
                    epochs=1)
# Save predictions for future checks
predictions = model.predict(x_test)

 

Whole-model saving

빌드된 모델을 하나로 저장할 수 있습니다. 모델을 만든 코드가 더 이상 남아있지 않더라도 이 파일을 통해 다시 사용할 수 있습니다.

파일에는 다음 내용이 포함됩니다.

  • 모델 구조
  • weight values
  • training config(compile)
  • optimizer and state
# Save the model
model.save('path_to_my_model.h5')

# Recreate the exact same model purely from the file
new_model = keras.models.load_model('path_to_my_model.h5')

import numpy as np

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)

# Note that the optimizer state is preserved as well:
# you can resume training where you left off.

 

Export to SavedModel

전체모델을 Tensorflow savedmodel format으로 추출할 수 있습니다. Tensorflow 객체용 독립형 serialization format이며 Python 이외의 Tensorflow 구현 뿐만아니라 Tensorflow Serving기능도 제공합니다.

# Export the model to a SavedModel
keras.experimental.export_saved_model(model, 'path_to_saved_model')

# Recreate the exact same model
new_model = keras.experimental.load_from_saved_model('path_to_saved_model')

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)

# Note that the optimizer state is preserved as well:
# you can resume training where you left off.

SavedModel은 다음을 포함합니다.

  • model weights를 포함한 Tensorflow checkpoint
  • Tensorflow graph가 포함된 SavedModel 프로토타입. 예측(Serving), 학습, 평가를 위한 별도의 그래프. 이전에 compile하지 않았다면, inference 그래프만 추출됨.
  • 모델 구조

 

Architecture-only saving

weight나 optimizer는 관심이 없고, 오로지 모델 구조에만 관심이 가는 경우가 있습니다. 이러한 경우에 get_config()를 통해 모델의 config를 검색하면 됩니다. 같은 모델을 재생성할 수 있도록 파이썬 dict구조로 되어 있습니다. 이렇게 불러진 모델은 이전에 학습한 정보는 가지고 있지 않습니다.

config = model.get_config()
reinitialized_model = keras.Model.from_config(config)

# Note that the model state is not preserved! We only saved the architecture.
new_predictions = reinitialized_model.predict(x_test)
assert abs(np.sum(predictions - new_predictions)) > 0.

python dict대신에 to_json(), from_json()을 사용하여 JSON으로도 저장할 수 있습니다. disk에 저장할 때 유용하게 사용됩니다.

json_config = model.to_json()
reinitialized_model = keras.models.model_from_json(json_config)

 

Weights-only saving

weights에만 관심이 있는 경우에 get_weights()를 사용하여 Numpy array로 이루어진 weights를 찾을 수 있습니다. 또한, 모델의 상태를 set_weights로 변경할 수 있습니다.

weights = model.get_weights()  # Retrieves the state of the model.
model.set_weights(weights)  # Sets the state of the model.

get_config() / from_config() 와 get_weights() / set_weights()를 적절히 섞어 사용할 수 있습니다. 하지만, model.save()와는 다르게 이들은 학습 config와 optimizer를 포함하지 않습니다. 따라서 compile을 다시 설정해주어야 합니다.

config = model.get_config()
weights = model.get_weights()

new_model = keras.Model.from_config(config)
new_model.set_weights(weights)

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)

# Note that the optimizer was not preserved,
# so the model should be compiled anew before training
# (and the optimizer will start from a blank state).

get_weights() / set_weights()와 같은 의미이면서 디스크에 저장하려면 save_weighs(fpath) / load_weights(fpath)를 사용하면 됩니다.

# Save JSON config to disk
json_config = model.to_json()
with open('model_config.json', 'w') as json_file:
    json_file.write(json_config)
# Save weights to disk
model.save_weights('path_to_my_weights.h5')

# Reload the model from the 2 files we saved
with open('model_config.json') as json_file:
    json_config = json_file.read()
new_model = keras.models.model_from_json(json_config)
new_model.load_weights('path_to_my_weights.h5')

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)

# Note that the optimizer was not preserved.

이는 너무 복잡하니 다음과 같은 방법을 추천드립니다.

model.save('path_to_my_model.h5')
del model
model = keras.models.load_model('path_to_my_model.h5')

 

Weights-only saving in SavedModel format

save_weights는 keras에서 HDF5 format, Tensorflow에서 SavedModel format 형태를 만들어 냅니다. 이러한 형식은 사용자가 제공하는 되로 선택되어집니다. ".h5", "keras"인 경우는 Keras HDF5 형식을 사용합니다. 다른 모든 항목은 SavedModel로 기본 설정 됩니다.

model.save_weights('path_to_my_tf_savedmodel')

명시적으로 save_format인자("tf" or "h5")를 전달하여 설정할 수 있습니다. 

model.save_weights('path_to_my_tf_savedmodel', save_format='tf')

 

Saving Subclassed Models

Sequential, Functional Model은 DAG of layers를 나타내는 데이터구조입니다. 이들은 안전하게 serialized, deserialized될 수 있습니다.

subclassed되어진 모델은 데이터 구조가 아닌 그저 코드의 일부분일 뿐입니다. 이러한 모델의 구조는 call method에서 정의됩니다. 이는 모델이 안전하게 serialized될 수 없다는 것을 의미합니다.

모델을 불러오기 위해, 모델을 생성한 코드(the code of the model subclass)에 접근할 수 있어야합니다. 대신, 이러한 코드를 바이트코드(pickling)로 serializing할 수 있지만 안전하지 않습니다.

class ThreeLayerMLP(keras.Model):

  def __init__(self, name=None):
    super(ThreeLayerMLP, self).__init__(name=name)
    self.dense_1 = layers.Dense(64, activation='relu', name='dense_1')
    self.dense_2 = layers.Dense(64, activation='relu', name='dense_2')
    self.pred_layer = layers.Dense(10, activation='softmax', name='predictions')

  def call(self, inputs):
    x = self.dense_1(inputs)
    x = self.dense_2(x)
    return self.pred_layer(x)

def get_model():
  return ThreeLayerMLP(name='3_layer_mlp')

model = get_model()

우선, 한번도 사용되지 않은 모델은 저장할 수 없습니다. 

subclassed model은 weights를 생성하기 위해 한번쯤은 데이터가 필요하기 때문입니다. 

모델이 호출될 때 까지, input dtype, shape를 알 수 없고 weight variable또한 마찬가지입니다. Functional Model은 가장 처음에 keras.Input을 통해 input dtype, shape를 정의하기 때문에 이러한 문제가 없습니다. 

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

model.compile(loss='sparse_categorical_crossentropy',
              optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train,
                    batch_size=64,
                    epochs=1)

subclassed model을 저장하는데에 추천하는 방법은 model과 연관된 모든 variable을 담고있는 Tensorflow SavedModel checkpoint를 만드는 save_weights()를 사용하는 것입니다.(weights, optimizer state, etc.)

model.save_weights('path_to_my_weights', save_format='tf')

# Save predictions for future checks
predictions = model.predict(x_test)
# Also save the loss on the first batch
# to later assert that the optimizer state was preserved
first_batch_loss = model.train_on_batch(x_train[:64], y_train[:64])

모델을 복원하기 위해선 만들어진 모델 객체에 접근할 수 있어야합니다.

metric, optimizer의 상태를 복원하려면 model을 compile하고 load_weights를 호출하기 전에 일부 데이터를 호출해야합니다.

# Recreate the model
new_model = get_model()
new_model.compile(loss='sparse_categorical_crossentropy',
                  optimizer=keras.optimizers.RMSprop())

# This initializes the variables used by the optimizers,
# as well as any stateful metric variables
new_model.train_on_batch(x_train[:1], y_train[:1])

# Load the state of the old model
new_model.load_weights('path_to_my_weights')

# Check that the model state has been preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)

# The optimizer state is preserved as well,
# so you can resume training where you left off
new_first_batch_loss = new_model.train_on_batch(x_train[:64], y_train[:64])
assert first_batch_loss == new_first_batch_loss

Abstract

We present the first deep learning model to successfully learn control policies directly from high-dimensional sensory input using reinforcement learning. The model is a convolutional neural network, trained with a variant of Q-learning, whose input is raw pixels and whose output is a value function estimating future rewards. We apply our method to seven Atari 2600 games from the Arcade Learning Environment, with no adjustment of the architecture or learning algorithm. We find that it outperforms all previous approaches on six of the games and surpasses a human expert on three of them.


우리는 강화학습을 사용하여 고차원 sensory input을 직접 control 정책을 성공적으로 학습한 딥러닝 모델을 제시한다.

input이 raw pixel이고, output이 미래 보상을 추정하는 가치함수인 변형된 Q-learning으로 학습된 CNN으로 이루어져 있다.

이 방법을 학습 알고리즘이나 아키텍처를 변형하지 않고, 아케이트 학습 환경에서 얻어진 7개의 아타리 2600게임에 적용했다.

6개의 게임이 모두 이전에 제시된 방법보다 outperform하였고, 그 중 3개는 인간의 수준을 넘어섰다.


요약

  • 이전의 연구들은(6가지 게임에 대해) 결과가 좋지 않으며, 최근 deep learning의 여러 방법들을 적용하였지만 좋은 결과를 얻진 못하였다. data sample independent를 만족하지 못하였기 때문.
  • 위 방법은 기존 강화학습에서 사용하기엔 상당히 챌린지하며, 이를 해결하기 위해 Experience replay와 CNN with varient Q-learning을 사용하였다.
  • 기존 deep learning은 batch를 이용하여 학습 시켰을때 좋은 결과를 얻었는데, 강화학습에서는 sequence로 나오기 때문에 이를 사용할 수 없었다. 따라서 연구팀은 내가 원하는 만큼의 sequence를 미리 저장해 두었다가 이를 batch training하겠다는 것이 핵심 novelity라고 할 수 있다.
  • 이론적으로 자세히 증명하진 못했으나 Q가 상당히 잘 수렴하였다.

 

Reference

Mnih, V., Kavukcuoglu, K., Silver, D., Graves, A., Antonoglou, I., Wierstra, D., & Riedmiller, M. (2013). Playing atari with deep reinforcement learning. arXiv preprint arXiv:1312.5602.