Keras 스타일 이전 실현

10258 단어
풍격 이 바뀌다.
스타일 이전 알고리즘 은 여러 차례 정의 와 업 데 이 트 를 거 쳐 현재 많은 스마트 폰 앱 에 응용 되 고 있다.스타일 이전 은 목표 이미지 내용 을 유지 하 는 토대 에서 이미지 스타일 을 목표 이미지 에 참조 합 니 다.스타일 은 본질 적 으로 각종 공간 척도 에서 이미지 의 무늬, 색채 와 시각 도안 을 말한다.내용 은 이미지 의 고급 거시적인 구조 이다.스타일 이전 뒤의 관건 적 인 개념 은 모든 깊이 있 는 학습 알고리즘 의 핵심 과 같다. 손실 함 수 를 정의 하여 실현 하고 자 하 는 목 표를 지정 하고 이런 손실 을 최대한 줄인다.자신 이 실현 하고 자 하 는 목 표를 알 고 있 습 니 다. 이미지 의 스타일 을 참고 하 는 동시에 원본 이미지 의 내용 을 보존 합 니 다.만약 우리 가 수학 적 으로 내용 과 스타일 을 정의 할 수 있다 면, 최소 화 된 적당 한 손실 함 수 는 다음 과 같은 내용 입 니 다: loss = distance (style (reference image) - style (generated image) + distance (content (original image) - content (generated image)
distance 는 L2 범 수의 함수 로 content 가 그림 내용 을 계산 하여 표시 하 는 함수 입 니 다.style 그림 스타일 표시 함수 계산.손실 함수 최소 화 는 style (generated image) 과 참조 이미지 style (reference image) 을 가능 한 한 접근 시 키 고, content (generated image) 는 콘 텐 츠 이미지 content (original image) 와 가능 한 한 접근 하여 스타일 이전 목 표를 달성 합 니 다.
내용 손실 함수
우 리 는 네트워크 모델 앞의 몇 층 의 활성화 함수 값 이 그림 의 국부 정 보 를 나타 내 는 것 을 이미 알 고 있다. 고 층 네트워크 활성화 값 은 전역 적 이 고 추상 적 인 특징 정 보 를 포함한다.다시 말 하면 볼 륨 망 의 서로 다른 층 의 활성화 치 는 서로 다른 공간 척도 에서 이미지 내용 의 분 해 를 제공 한 다 는 것 이다.따라서 convnet 의 상부 표 시 를 통 해 더욱 전면적 이 고 추상 적 인 이미지 내용 을 포착 하 기 를 기대한다.콘 텐 츠 손실 함수 의 또 다른 선택 은 대상 이미지 에서 계 산 된 프 리 트 레이 닝 네트워크 의 상부 활성화 와 생 성 된 이미지 에서 계 산 된 동일 층 활성화 사이 의 L2 범 수 입 니 다.이것 은 상부 에서 본 생 성 된 이미지 가 원시 목표 이미지 와 유사 해 보일 수 있 도록 보장 한다.볼 륨 망 의 상층 부 에서 그림 을 입력 하 는 내용 을 본다 고 가정 하면 이것 이 바로 이미지 내용 을 저장 하 는 방식 이다.
스타일 손실 함수
콘 텐 츠 손실 함 수 는 하나의 상층 부 만 사용 하지만 Gatys 가 정의 하 는 스타일 손실 함 수 는 여러 개의 convnet 층 을 사용 합 니 다. convnet 에서 추출 한 모든 공간 비율의 스타일 참조 이미지 의 외관 을 캡 처 하려 고 합 니 다. 단일 비율 만 이 아 닙 니 다.스타일 의 손실 에 대해 Gatys 는 그래 픽 을 사용 하여 활성 화 된 Gram 매트릭스: 주어진 그래 픽 의 요소 그림 의 내 적 을 사용 합 니 다.이 내 적 은 층 의 특징 간 의 상관 성 을 나타 내 는 그림 으로 이해 할 수 있다.이러한 특징 은 관련 성 이 특정 공간 척도 모델 의 통계 데 이 터 를 포착 하고 경험 적 으로 이 척도 에서 찾 은 무늬 의 외관 에 대응한다.따라서 스타일 손실 은 스타일 참조 이미지 와 생 성 된 이미지 사이 에 서로 다른 층 의 활성화 내 유사 한 내부 상관 성 을 유지 하 는 데 목적 을 둔다.반대로 이것 은 서로 다른 공간의 척도 에서 찾 은 무늬 가 스타일 참조 이미지 와 생 성 된 이미지 에서 비슷 해 보 이 는 것 을 보장 한다.
미리 훈련 된 네트워크 모델 을 사용 하여 손실 함 수 를 정의 할 수 있 습 니 다.
  • 대상 콘 텐 츠 이미지 와 생 성 된 이미지 사이 에 유사 한 고급 그래 픽 을 유지 하여 콘 텐 츠 를 보존 합 니 다.볼 륨 망 은 대상 이미지 와 생 성 된 이미지 가 같은 내용 을 포함 하 는 것 을 보아 야 합 니 다.
  • 저급 도 층 과 고급 도 층 의 활성화 에서 유사 한 상관 성 을 유지 함으로써 스타일 을 보존 합 니 다.특징 관련 성 포획 무늬: 생 성 된 이미지 와 스타일 참조 이미 지 는 서로 다른 공간 척도 에서 같은 무늬 를 공유 해 야 한다.

  • Keras 실현
    VGG 19 네트워크 모델 을 사용 하여 스타일 이전 을 실현 합 니 다.흐름:
  • 네트워크 를 설정 하고 스타일 을 위해 그림 을 참고 하 며 대상 이미지 와 생 성 이미지 로 VGG 19 그림 층 활성화 함수 값 을 계산 합 니 다.
  • 이 세 이미지 에서 계 산 된 그래 픽 활성화 값 을 사용 하여 앞에서 설명 한 손실 함 수 를 정의 하고 스타일 이전 을 최소 화 할 수 있 습 니 다.
  • 이 손실 함 수 를 최소 화하 기 위해 경사도 하강 과정 을 설정 합 니 다.

  • 스타일 그림, 대상 그림 경로 주 소 를 정의 합 니 다.두 장의 처리 그림 의 크기 가 같 도록 (크기 가 다 르 면 처리 난이도 가 증가 합 니 다) 두 장의 그림 을 resize 작업 을 하고 크기 는 400 px 입 니 다.초기 변수 정의
    from keras.preprocessing.image import load_img,img_to_array
    
    target_image_path = 'img/protrait.jpg'
    style_reference_image_path = 'img/transfer_style_reference.jpg'
    
    width, height = load_img(target_image_path).size
    img_height = 400
    img_width = int(width*img_height/height)

    보조 함 수 를 정의 하여 불 러 오기 편리, 예 처리, 후기 처리 VGG 19 볼 륨 네트워크 수신 과 생 성 된 그림 을 정의 합 니 다.보조 함수
    import numpy as np
    from keras.applications import vgg19
    
    def preprocess_image(image_path):
        img = load_img(image_path,target_size=(img_height,img_width))
        img = img_to_array(img)
        img = np.expand_dims(img,axis=0)
        img = vgg19.preprocess_input(img)
        return img
        
    def deprocess_image(x):
        x[:,:,0] += 103.939#zero-centering 0   :    
        x[:,:,1] += 116.779
        x[:,:,2] += 123.68
        x = x[:,:,::-1]#BGR---> RGB
        x = np.clip(x,0,255).astype('uint8')
        return x

    vgg 19 네트워크 설정.스타일 이미지, 대상 이미지, 그림 을 만 드 는 placeholder 세 장의 그림 을 batch 로 입력 합 니 다.
    예비 훈련 VGG 19 모델 로드, 응용
    from keras import backend as K
    
    target_image = K.constant(preprocess_image(target_image_path))
    style_reference_image=K.constant(preprocess_image(style_reference_image_path))
    combination_image = K.placeholder((1,img_height,img_width,3))#      
    input_tensor = K.concatenate([target_image,style_reference_image,
        combination_image],axis=0)#      
    model = vgg19.VGG19(input_tensor=input_tensor,weights='imagenet',include_top=False)
    
    print("Model loaded.")

    콘 텐 츠 손실 을 정의 하여 대상 이미지 와 생 성 이미지 가 VGG 19 볼 륨 네트워크 의 상부 네트워크 에서 비슷 하도록 합 니 다.내용 손실
    def content_loss(base,combination):
        return K.sum(K.square(combination-base))

    스타일 손실 정의.보조 함 수 를 사용 하여 Gram 행렬 을 계산 합 니 다: 원시 특징 행렬 에서 찾 은 관련 그림 입 니 다.스타일 손실
    def gram_matrix(x):
        features = K.batch_flatten(K.permute_dimensions(x,(2,0,1)))
        gram = K.dot(features,K.transpose(features))
        return gram
        
    def style_loss(style,combination):
        S = gram_matrix(style)
        C = gram_matrix(combination)
        channels = 3
        size = img_height*img_width
        return K.sum(K.square(S-C)) / (4.*(channels ** 2) * (size ** 2))

    이 두 가지 손실 함 수 를 제외 하고 세 번 째: 총 변이 손실 을 추가 하여 생 성 된 조합 이미지 의 픽 셀 을 조작 합 니 다.이 는 생 성 된 이미지 의 공간 연속 성 을 장려 하여 과도 한 픽 셀 화 결 과 를 피한다.이 를 정규 화 손실 로 해석 할 수 있다.변이 손실
    def total_variation_loss(x):
        a = K.square(
            x[:,:img_height-1,:img_width-1,:]-
            x[:,1:,:img_width-1,:]
        )
        b = K.square(
            x[:,img_height-1,:img_width-1,:] - 
            x[:,:img_height-1,1:,:]
        )
        return K.sum(K.pow(a+b, 1.25))

    손실 함 수 를 최소 화 하 는 것 은 세 가지 손실 함수 의 가중 평균 이다.내용 손실 을 계산 하기 위해 서 는 상부 네트워크 인 block 5 만 사용 해 야 합 니 다.conv 2 네트워크 층;스타일 손실 을 계산 하려 면 여러 개의 네트워크 층 을 사용 해 야 한다. 바 텀 네트워크 에서 고 층 네트워크 까지.마지막 으로 변이 손실 까지.
    스타일 이미지 와 콘 텐 츠 이미지 사용 에 의존 하여 콘 텐 츠 를 약간 조정 해 야 할 수도 있 습 니 다weight 계수.대 콘 텐 츠weight 는 목표 내용 이 생 성 된 그림 에서 쉽게 식별 된다 는 것 을 의미한다.최종 손실 함수 정의
    output_dict = dict([(layer.name,layer.output) for layer in model.layers])
    content_layer = 'block5_conv2'
    style_layers = ['block1_conv1','block2_conv1',
        'block3_conv1','block4_conv1','block5_conv1']
    
    total_variation_weight = 1e-4
    style_weight = 1.
    content_weight = 0.025
    
    loss = K.variable(0.)#     
    layer_features = outputs_dict[content_layer]
    target_image_features = layer_features[0, :, :, :]
    combination_features = layer_features[2, :, :, :]
    loss+=content_weight*content_loss(target_image_features,combination_features)#     
    
    for layer_name in style_layers:#     
        layer_features = outputs_dict[layer_name]
        style_reference_features = layer_features[1, :, :, :]
        combination_features = layer_features[2, :, :, :]
        sl = style_loss(style_reference_features, combination_features)
        loss += (style_weight / len(style_layers)) * sl
    
    #     ,         
    loss += total_variation_weight * total_variation_loss(combination_image)

    마지막 으로 경사도 하강 알고리즘 을 사용한다.Gatys 논문 에 서 는 L - BFGS 알고리즘 을 사용 했다.L - BFGS 알고리즘 은 Scipy 패키지 에 포함 되 어 있 으 며 Scipy 구현 에 두 가지 제한 이 있 습 니 다.
  • 요구 하 는 손실 함수 값, 경사도 함수 값 은 두 개의 독립 된 함수 로 전달 된다.
  • 플랫 은 벡터 를 펼 쳐 야 하고 그림 배열 은 3D 입 니 다.

  • 손실 함수 의 값 과 경사도 의 값 을 단독으로 계산 하 는 것 은 비효 율 적 이다. 이렇게 하면 이들 사이 의 대량의 잉여 계산 을 초래 할 수 있 기 때문이다.이 과정 은 거의 공동 계산 과정의 두 배 이다.이 를 돌아 가 려 면 Evaluator 라 는 Python 류 를 설정 하고 손실 값 과 경사도 값 을 계산 하 며 첫 번 째 호출 시 손실 값 을 되 돌려 주 고 다음 호출 경사도 를 캐 시 합 니 다.경사도 업데이트
    grads = K.gradients(loss, combination_image)[0]
    fetch_loss_and_grads = K.function([combination_image], [loss, grads])
    
    class Evaluator(object):
        def __init__(self):
            self.loss_value = None
            self.grads_values = None
            
        def loss(self, x):
            assert self.loss_value is None
            x = x.reshape((1, img_height, img_width, 3))
            outs = fetch_loss_and_grads([x])
            loss_value = outs[0]
            grad_values = outs[1].flatten().astype('float64')
            self.loss_value = loss_value
            self.grad_values = grad_values
            return self.loss_value
            
        def grads(self, x):
            assert self.loss_value is not None
            grad_values = np.copy(self.grad_values)
            self.loss_value = None
            self.grad_values = None
            return grad_values
            
    evaluator = Evaluator()

    최종 적 으로 Scipy 의 L - BFGS 알고리즘 을 사용 하여 현재 생 성 된 그림 을 교체 할 때마다 경사도 가 낮 아 집 니 다.스타일 이동 순환
    from scipy.optimize import fmin_l_bfgs_b
    from scipy.misc import imsave
    import time 
    
    result_prefix = 'my_result'
    iterations = 20
    
    x = preprocess_image(target_image_path)#      
    x = x.flatten()#  ,  l-bfgs
    
    for i in range(iterations):
        print('Start of iteration', i)
        start_time = time.time()
        #        L-BFGS  ;                         
        x, min_val, info = fmin_l_bfgs_b(evaluator.loss, x,
                fprime=evaluator.grads,maxfun=20)
        print('Current loss value:', min_val)
        img = x.copy().reshape((img_height, img_width, 3))
        img = deprocess_image(img)
        fname = result_prefix + '_at_iteration_%d.png' % i
        imsave(fname, img)
        print('Image saved as', fname)
        end_time = time.time()
        print('Iteration %d completed in %ds' % (i, end_time - start_time))
    

    이런 기술 이 실현 하 는 것 은 이미지 재 구성 이나 무늬 전이 의 한 형식 일 뿐 이라는 것 을 기억 하 세 요.이 는 강력 한 무늬 와 고도 의 유사 성 을 가 진 스타일 참조 이미지 에 가장 적합 하 며, 내용 목 표 는 식별 할 수 있 도록 높 은 수준의 디 테 일 을 필요 로 하지 않 는 다.그것 은 보통 초상 의 풍격 을 다른 초상 으로 옮 기 는 등 상당히 추상 적 인 기능 을 실현 할 수 없다.이 알고리즘 은 AI 가 아 닌 고전 신호 처리 에 더 가깝다.
    또한 이 스타일 의 이전 알고리즘 을 실행 하 는 것 이 느 리 니 주의 하 세 요.그러나 설정 작업 의 전환 은 매우 간단 하 다. 적당 한 훈련 데이터 만 있 으 면 소형, 빠 른 피 드 볼 륨 네트워크 를 통 해 학습 할 수 있다.따라서 먼저 대량의 계산 주 기 를 들 여 고정 스타일 참조 이미지 의 입 출력 훈련 예 시 를 생 성하 고 개술 적 인 방법 을 사용 한 다음 에 간단 한 convnet 를 훈련 시 켜 이런 특정한 스타일 전환 을 학습 하여 빠 른 스타일 전환 을 실현 할 수 있다.일단 완성 되면 주어진 그림 을 스타일 화 하 는 것 은 즉각 적 인 것 이다. 이것 은 단지 이 작은 전방 향 전달 일 뿐이다.
    작은 매듭
  • 스타일 이전 은 새 그림 을 만 드 는 것 을 포함 합 니 다. 이 그림 은 대상 이미지 의 내용 을 유지 하 는 동시에 참고 이미지 의 스타일 도 캡 처 합 니 다.
  • 내용 은 볼 륨 네트워크 의 고 층 네트워크 를 통 해 포착 할 수 있다.
  • 스타일 은 볼 륨 네트워크 의 서로 다른 네트워크 층 을 통 해 함수 의 내부 상관 성 계산 을 활성화 합 니 다.
  • 따라서 심도 있 는 학습 은 스타일 이전 을 예비 훈련 된 convnet 을 사용 하여 정 의 된 손실 을 최적화 하 는 과정 으로 표현 할 수 있다.

  • 다음으로 전송:https://www.cnblogs.com/ysugyl/p/9574474.html

    좋은 웹페이지 즐겨찾기