मुख्य सामग्री पर जाएँ

TensorFlow 2.0 का उपयोग करके Neural Style Transfer लागू करना

इस ट्यूटोरियल में, आप सीखेंगे कि TensorFlow 2.0 का उपयोग करके Prisma जैसी पावर एप्लिकेशन कैसे लागू करें।
· 11 मि॰ पढ़ें

AI के साथ खोजें

चित्र वर्गीकरण और विश्लेषण के लिए कन्वोल्यूशनल न्यूरल नेटवर्क्स सबसे शक्तिशाली प्रकार के न्यूरल नेटवर्क हैं। इनके अनुप्रयोग कई सीमाओं को पार कर चुके हैं और आज हम जिन कई डीप लर्निंग-सक्षम अनुप्रयोगों को देखते हैं, उनके महत्वपूर्ण घटक साबित हुए हैं। उच्च स्तर पर, CNNs उन छवियों के आंतरिक फीचर-स्तरीय निरूपण सीख सकते हैं जो उन्हें दी जाती हैं। यही इन्हें इतना शक्तिशाली बनाता है। दिलचस्प बात यह है कि CNNs की यह प्रमुख विशेषता केवल छवि वर्गीकरण जैसे कार्यों में ही नहीं, बल्कि छवि निर्माण में भी उपयोगी है। Deep Dream और Neural Style Transfer जैसी एप्लिकेशन, CNNs की लेयर एक्टिवेशन्स और उनसे निकाले गए फीचर्स के आधार पर छवियाँ संयोजित करती हैं।

इस ट्यूटोरियल में, आप पढ़ेंगे कि Neural Style Transfer कैसे काम करता है और इसे TensorFlow 2.0 का उपयोग करके कैसे लागू किया जा सकता है।

ध्यान दें कि इस ट्यूटोरियल के साथ आगे बढ़ने के लिए, आपको CNNs के काम करने का तरीका पता होना चाहिए। यदि आप CNNs पर त्वरित रिफ्रेशर के लिए संसाधन ढूंढ रहे हैं, तो निम्नलिखित आज़माएँ:

Neural Style Transfer क्या है?

कंप्यूटर विज़न और डीप लर्निंग क्षेत्र में नए प्रवेशकों के लिए, neural style transfer शब्द थोड़ा भारी लग सकता है। इस शब्द के प्रत्येक घटक को समझने के लिए, नीचे दी गई दो छवियों पर विचार करें:

neural style transfer 1

Neural style transfer के संदर्भ में, बाईं छवि को content छवि कहा जाता है और दाईं ओर की छवि को style छवि। आप एक छवि (यहाँ बाईं) को दूसरी छवि (दाईं) की शैली से स्टाइलाइज़ करना चाहते हैं। यही शब्द के अंतिम दो शब्दों का निर्माण करता है — style transfer। इस प्रक्रिया को अंजाम देने के लिए, एक न्यूरल नेटवर्क (CNN) को एक कस्टम लॉस फ़ंक्शन को ऑप्टिमाइज़ करने के लिए प्रशिक्षित किया जाता है, इसलिए पहला शब्द — neural। जब ऊपर दी गई दोनों छवियों को neural style transfer का उपयोग करके मिलाया जाता है, तो अंतिम आउटपुट (दाईं ओर) कुछ इस प्रकार दिखता है —

neural style transfer 2

आप पूछ सकते हैं कि neural style transfer का उपयोग क्या है? कल्पना कीजिए कि आपके पास Vincent van Gogh द्वारा बनाई गई एक ड्राइंग की छवि है। आप देखना चाहते हैं कि यह ड्राइंग आपकी अपनी किसी ड्राइंग पर कैसी दिखती। यह neural style transfer का एक उपयोग है। एक और उदाहरण कई फोटो फ़िल्टर एप्लिकेशन जैसे Prisma हैं, जो आपको एक सहज यूज़र इंटरफ़ेस के जरिए neural style transfer करने देते हैं।

Content और Style के बीच पृथक्करण

अब तक, आपके मन में neural style transfer के बारे में जो धारणा बनी होगी, वह यह है कि यह प्रक्रिया एक छवि के कंटेंट को दूसरी की स्टाइल के साथ संयोजित करने के बारे में है। वास्तव में, यह 100% सही है। इस खंड में, समझते हैं कि CNNs के संदर्भ में कंटेंट और स्टाइल का वास्तव में क्या अर्थ है।

एक CNN आमतौर पर कई कन्वोल्यूशनल लेयर्स और पूलिंग लेयर्स का संग्रह होता है। कन्वोल्यूशनल लेयर्स किसी दी गई छवि से अत्यधिक जटिल फीचर्स निकालने के लिए ज़िम्मेदार होती हैं, जबकि पूलिंग लेयर्स वह विस्तृत स्थानिक जानकारी हटा देती हैं जो छवि वर्गीकरण समस्या के लिए प्रासंगिक नहीं होती। इसका प्रभाव यह होता है कि CNN किसी दी गई छवि के कंटेंट को सीखने में सक्षम होता है, न कि किसी विशिष्ट चीज़ जैसे रंग, टेक्सचर, आदि को। जैसे-जैसे हम CNN में गहराई में जाते हैं, फीचर्स की जटिलता बढ़ती है और गहरी कन्वोल्यूशनल लेयर्स को अक्सर कंटेंट निरूपण कहा जाता है।

स्टाइल का उदाहरण छवि गुणों की कोई भी विशिष्टता होगी जैसे टेक्सचर, रंग, आदि — जैसे किसी ड्राइंग में किसी विशेष रंग का प्रमुख उपयोग। अब प्रश्न यह है कि आप किसी छवि की स्टाइल कैसे निकालते हैं? यह कन्वोल्यूशनल लेयर्स के बीच सहसम्बंधन (correlations) की गणना करके किया जाता है। सहसम्बंधन हमें बताता है कि दो या अधिक चर कितने समान/संबंधित हैं। इसे समझने के लिए, एक सीखी हुई कन्वोल्यूशनल लेयर पर विचार करें जो कई फीचर मैप्स से बनी हो। प्रत्येक फीचर मैप के लिए, आप माप सकते हैं कि उसके द्वारा पहचाने गए फीचर्स उसी लेयर के अन्य फीचर मैप्स से कितने मज़बूती से संबंधित हैं। इससे आपको ऐसे अनुमानों का पता चलता है — क्या पहले फीचर मैप में पहचाना गया कोई रंग किसी अन्य मैप में मौजूद रंग से मिलता-जुलता है? क्या फीचर मैप्स में कुछ सामान्य आकृतियाँ हैं? ये विशेषताएँ/समानताएँ किसी छवि की स्टाइल को परिभाषित करती हैं। एक कन्वोल्यूशनल लेयर के भीतर कई फीचर मैप्स की सामग्रियों के बीच समानता मापने की प्रक्रिया नेटवर्क्स को दी गई छवि का बहु-स्तरीय निरूपण सीखने में मदद करती है, जो टेक्सचर और रंग जैसी स्थानिक विशेषताओं पर केंद्रित होता है।

एक महत्वपूर्ण बात जिसे ध्यान में रखना चाहिए, वह यह है कि neural style transfer लागू करते समय, आपको यह भी सुनिश्चित करना होता है कि किसी छवि का कंटेंट दूसरी छवि की वांछित स्टाइल के साथ-साथ संरक्षित रहे। आप आगे एक खंड में देखेंगे कि यह कैसे किया जाता है। अगले खंड में, आप सीखेंगे कि किसी छवि (कंटेंट इमेज) से फीचर्स कैसे निकाले जाते हैं और कंटेंट लॉस कैसे गणना किया जाता है।

Content इमेज का परिमाणीकरण और Content Loss की गणना

Neural style transfer एल्गोरिदम को सबसे पहले Gatys आदि ने 2015 के अपने पेपर A Neural Algorithm of Artistic Style में प्रस्तुत किया था। यह ट्यूटोरियल, हालांकि, Image Style Transfer Using Convolutional Neural Networks से संदर्भ लेता है, जो पहले उल्लिखित पेपर का एक प्रकार का विस्तार है।

Image Style Transfer Using Convolutional Neural Networks पेपर के अनुसार, यह कंटेंट और स्टाइल दोनों फीचर्स निकालने के लिए VGG-19 CNN आर्किटेक्चर का उपयोग करता है। कंटेंट फीचर्स के लिए, चौथे ब्लॉक (कन्वोल्यूशनल लेयर्स के) की दूसरी कन्वोल्यूशनल लेयर का उपयोग किया जाता है। सुविधा के लिए, पेपर के लेखकों ने इसे conv4_2 नाम दिया। एक बार जब आप कंटेंट फीचर्स प्राप्त कर लेते हैं, तो आपको कंटेंट लॉस मापने के लिए इसे एक टारगेट इमेज से तुलना करनी होगी। टारगेट इमेज क्या है? यहाँ कंटेंट लॉस की गणना क्यों आवश्यक है? आइए एक कदम पीछे चलते हैं और इन दोनों प्रश्नों पर ध्यान केंद्रित करते हैं।

कंटेंट और स्टाइल फीचर्स को एक ही छवि में संयोजित करने के लिए, आपको एक टारगेट इमेज से शुरुआत करनी होगी, जो या तो खाली हो सकती है या कंटेंट इमेज की प्रति। अब, CNN का उपयोग करके कंटेंट और स्टाइल दोनों फीचर्स को प्रभावी रूप से सीखने के लिए, आपको एक कस्टम लॉस फ़ंक्शन की आवश्यकता होगी जिसे आप ऑप्टिमाइज़ करेंगे ताकि कंटेंट और स्टाइल छवियों से निर्मित एक स्मूद स्टाइलिस्टिक इमेज मिले। यह कस्टम लॉस फ़ंक्शन मूलतः दो अलग-अलग लॉसेस का सम्मिश्रण है:

  • कंटेंट लॉस, जो यह सुनिश्चित करता है कि कंटेंट की कुल मात्रा संरक्षित रहे।
  • स्टाइल लॉस, जो यह नियंत्रित करता है कि टारगेट इमेज में कितनी स्टाइल स्थानांतरित हो रही है।

अब जबकि आपको ऊपर दिए गए प्रश्नों का बोध हो गया है, आइए कंटेंट लॉस पर लौटते हैं और इसे परिभाषित करते हैं। कंटेंट लॉस को इस प्रकार परिभाषित किया जाता है —

जहाँ, $T_c$ टारगेट इमेज को और $C_c$ कंटेंट इमेज को संदर्भित करता है। तो, यह लॉस फ़ंक्शन जो कर रहा है, वह यह माप देना है कि कंटेंट और टारगेट इमेज के फीचर्स एक-दूसरे से कितने दूर हैं। नेटवर्क का उद्देश्य इस लॉस को न्यूनतम करना होता है। अगले खंड में, आप देखेंगे कि स्टाइल लॉस कैसे निर्धारित किया जाता है।

स्टाइल लॉस और Gram मैट्रिक्स

स्टाइल लॉस निर्धारित करने के लिए, पेपर निर्देश देता है कि आप निम्नलिखित लेयर्स से निरूपण (मूलतः संख्याएँ) लें और इन लेयर्स के भीतर फीचर मैप्स के ग्राम मैट्रिक्स प्राप्त करें।

'conv1_1'
'conv2_1'
'conv3_1'
'conv4_1'
'conv5_1'

स्टाइल लॉस को परिभाषित करने के लिए अनेक लेयर्स का उपयोग करने का लाभ यह है कि यह किसी छवि में निहित स्टाइल का बहु-स्तरीय निरूपण सीखने की अनुमति देता है। ग्राम मैट्रिक्स आपको यह निर्धारित करने में मदद करता है कि एक ही कन्वोल्यूशनल लेयर के भीतर फीचर मैप्स के पार फीचर्स कितने समान हैं। यह छवि के बारे में गैर-स्थानीयकृत जानकारी को दर्शाता है जो उसकी स्टाइल को आकार देती है। इस संदर्भ में एक ग्राम मैट्रिक्स निम्न प्रकार से गणना किया जाता है।

मान लीजिए किसी convolved इमेज का आयाम 8x8x16 है, जो मुख्य रूप से बताता है कि इसमें 16 फीचर मैप्स हैं। अब आप इन फीचर मैप्स के पार फीचर्स के बीच समानताएँ ग्राम मैट्रिक्स का उपयोग करके ढूंढना चाहते हैं। इसके लिए, आप convolved इमेज के पहले दो आयामों को समतल (flatten) कर 1D वेक्टर में बदल देते हैं। इस मामले में फ्लैट करने पर आयाम 1D वेक्टर में 64 प्रविष्टियाँ रखेगा। यह सभी फीचर मैप्स के लिए दोहराया जाता है। तो, आपको अंतिम मैट्रिक्स 16x64 आयाम का मिलता है (मान लें मैट्रिक्स A)। फिर इस मैट्रिक्स को ट्रांसपोज़ (64x16) कर मैट्रिक्स A से गुणा किया जाता है। इस मामले में ग्राम मैट्रिक्स 16x16 आयाम का होगा। ग्राम मैट्रिक्स में कोई विशेष मान फीचर मैप्स के बीच समानताओं को दर्शाएगा। दृश्य रूप में यह प्रक्रिया कुछ इस प्रकार दिखती है:

style loss and gram matrix

टारगेट और स्टाइल इमेजेज़ के बीच स्टाइल लॉस की गणना करने के लिए, आप प्रत्येक कन्वोल्यूशनल लेयर ब्लॉक पर उनके ग्राम मैट्रिक्स के बीच औसत वर्ग दूरी (mean squared distances) लेते हैं। औपचारिक रूप से, इसे निम्न प्रकार परिभाषित किया जा सकता है:

जहाँ, T(s,i) ब्लॉक i पर गणना किया गया टारगेट इमेज का ग्राम मैट्रिक्स है और S(s,i) ब्लॉक i पर गणना किया गया स्टाइल इमेज का ग्राम मैट्रिक्स है। wi के साथ, आप विभिन्न कन्वोल्यूशन ब्लॉक्स को कस्टम वेट्स दे सकते हैं ताकि स्टाइल का विस्तृत निरूपण प्राप्त हो सके। अंत में, $a$ एक स्थिरांक है जो ब्लॉक्स के भीतर प्रत्येक लेयर के मानों का लेखा रखता है। आइए दोनों लॉसेस को साथ रखकर उस कुल लॉस को परिभाषित करें जिसे नेटवर्क neural style transfer की प्रक्रिया में ऑप्टिमाइज़ करता है।

कुल लॉस परिभाषित करना

अब कुल लॉस कस्टम वेट्स के साथ जोड़ का मात्र मामला है —

जहाँ, $\alpha$ कंटेंट वेट को और $\beta$ स्टाइल वेट को दर्शाता है। यह आपको कंटेंट और टारगेट इमेज में स्थानांतरित हो रही स्टाइल की मात्रा के बीच अच्छा संतुलन बनाए रखने में मदद करता है। $\alpha$ और $\beta$ के विभिन्न संयोजनों का प्रभाव पेपर में देखा जा सकता है, और आपको उसे देखने के लिए प्रोत्साहित किया जाता है। अब आपके पास neural style transfer को लागू करने के लिए सभी हिस्से मौजूद हैं। अगले खंड में सीधे इस पर काम करते हैं।

Neural Style Transfer व्यवहार में

इम्प्लीमेंटेशन के लिए आप TensorFlow 2.0 का उपयोग करेंगे। इसमें कई असाधारण जोड़ हैं और यह अब तक की सबसे व्यापक अपडेट्स में से एक है। यदि आप इनमें से कुछ के बारे में सीखने में रुचि रखते हैं, तो यह लेख देखें।

TensorFlow का नवीनतम संस्करण (इस ट्यूटोरियल को लिखते समय) 2.0.0-beta0 है। यदि आपने अभी तक यह इंस्टॉल नहीं किया है, तो कृपया यहाँ दिए गए निर्देशों का पालन करके पहले इसे इंस्टॉल करें। आप आवश्यक पैकेजों और कंटेंट व स्टाइल इमेजेज़ को इम्पोर्ट करके शुरू करेंगे।

# Packages
import tensorflow as tf
from tensorflow.keras.applications.vgg19 import preprocess_input
from tensorflow.keras.models import Model
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(7)

%matplotlib inline

print(tf.__version__)
2.0.0-beta0
# Load the content and style images
content = plt.imread('Content.jpeg')
style = plt.imread('Style.jpg')

# Display the images
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10))

# Content and style images side-by-side
ax1.imshow(content)
ax1.set_title('Content Image')
ax2.imshow(style)
ax2.set_title('Style Image')
plt.show()
content and style images

अगले चरण में, आप एक हेल्पर फ़ंक्शन लिखेंगे जो दोनों इमेजेज़ को अंकों की ऐरे में लोड करेगा (क्योंकि कंप्यूटर केवल संख्याएँ समझते हैं) और उन्हें मॉडल के साथ संगत बनाने के लिए उनका आकार बदलेगा।

def load_image(image):
  image = plt.imread(image)
  img = tf.image.convert_image_dtype(image, tf.float32)
  img = tf.image.resize(img, [400, 400])
  # Shape -> (batch_size, h, w, d)
  img = img[tf.newaxis, :]
  return img
# Use load_image of content and style images
content = load_image('Content.jpeg')
style = load_image('Style.jpg')

# Verify the shapes
content.shape, style.shape
(TensorShape([1, 400, 400, 3]), TensorShape([1, 400, 400, 3]))

इमेजेज़ का आकार बदल दिया गया है। अब, आप फीचर्स निकालने के लिए एक प्री-ट्रेंड VGG19 मॉडल लोड करेंगे। क्योंकि आप मॉडल का उपयोग केवल फीचर्स निकालने के लिए करेंगे, आपको मॉडल के क्लासिफ़ायर भाग की आवश्यकता नहीं होगी।

vgg = tf.keras.applications.VGG19(include_top=False, weights='imagenet')
vgg.trainable = False
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5
80142336/80134624 [==============================] - 5s 0us/step

लेखकों ने उन ब्लॉक नामों को निर्दिष्ट किया है जिनका उपयोग उन्होंने कंटेंट और स्टाइल फीचर्स निकालने के लिए किया था। आपने जो VGG19 मॉडल अभी लोड किया है, उसमें वही नामकरण प्रथा है। तो इसका लाभ उठाने के लिए, आप पहले नेटवर्क में मौजूद सभी लेयर्स के नाम प्रिंट करेंगे।

# Print the layer names for convenience
for layer in vgg.layers:
  print(layer.name)
input_1
block1_conv1
block1_conv2
block1_pool
block2_conv1
block2_conv2
block2_pool
block3_conv1
block3_conv2
block3_conv3
block3_conv4
block3_pool
block4_conv1
block4_conv2
block4_conv3
block4_conv4
block4_pool
block5_conv1
block5_conv2
block5_conv3
block5_conv4
block5_pool

हालाँकि, आप स्टाइल फीचर्स के लिए निम्नलिखित में रुचि रखते हैं:

'conv1_1'
'conv2_1'
'conv3_1'
'conv4_1'
'conv5_1'

कंटेंट फीचर्स के लिए, आपको conv4_2 की आवश्यकता होगी। आप इन्हें तदनुसार वेरिएबल्स में संग्रहित करेंगे।

# Content layer
content_layers = ['block4_conv2']

# Style layer
style_layers = ['block1_conv1',
                'block2_conv1',
                'block3_conv1',
                'block4_conv1',
                'block5_conv1']


num_content_layers = len(content_layers)
num_style_layers = len(style_layers)

अब एक कस्टम VGG मॉडल बनाएँ जो निर्दिष्ट लेयर्स से मिलकर बना हो। यह आपको इमेजेज़ पर फॉरवर्ड पास चलाने और रास्ते में आवश्यक फीचर्स निकालने में मदद करेगा।

def mini_model(layer_names, model):

  outputs = [model.get_layer(name).output for name in layer_names]

  model = Model([vgg.input], outputs)
  return model

TensorFlow में ग्राम मैट्रिक्स को परिभाषित करना बहुत आसान है, और आप इसे निम्न तरीके से कर सकते हैं:

# Gram matrix
def gram_matrix(tensor):
  temp = tensor
  temp = tf.squeeze(temp)
  fun = tf.reshape(temp, [temp.shape[2], temp.shape[0]*temp.shape[1]])
  result = tf.matmul(temp, temp, transpose_b=True)
  gram = tf.expand_dims(result, axis=0)
  return gram

अब आप mini_model() फ़ंक्शन का उपयोग करके एक कस्टम मॉडल परिभाषित करेंगे। यह संबंधित इमेजेज़ से कंटेंट और स्टाइल फीचर्स लौटाने के लिए इस्तेमाल होगा।

 class Custom_Style_Model(tf.keras.models.Model):
  def __init__(self, style_layers, content_layers):
    super(Custom_Style_Model, self).__init__()
    self.vgg =  mini_model(style_layers + content_layers, vgg)
    self.style_layers = style_layers
    self.content_layers = content_layers
    self.num_style_layers = len(style_layers)
    self.vgg.trainable = False

  def call(self, inputs):
    # Scale back the pixel values
    inputs = inputs*255.0
    # Preprocess them with respect to VGG19 stats
    preprocessed_input = preprocess_input(inputs)
    # Pass through the mini network
    outputs = self.vgg(preprocessed_input)
    # Segregate the style and content representations
    style_outputs, content_outputs = (outputs[:self.num_style_layers],
                                      outputs[self.num_style_layers:])

    # Calculate the gram matrix for each layer
    style_outputs = [gram_matrix(style_output)
                     for style_output in style_outputs]

    # Assign the content representation and gram matrix in
    # a layer by layer fashion in dicts
    content_dict = {content_name:value
                    for content_name, value
                    in zip(self.content_layers, content_outputs)}

    style_dict = {style_name:value
                  for style_name, value
                  in zip(self.style_layers, style_outputs)}

    return {'content':content_dict, 'style':style_dict}

अब जबकि आपने कस्टम मॉडल परिभाषित कर लिया है, आइए इसे इमेजेज़ पर उपयोग करें ताकि क्रमशः कंटेंट और स्टाइल फीचर्स प्राप्त किए जा सकें —

# Note that the content and style images are loaded in
# content and style variables respectively
extractor = Custom_Style_Model(style_layers, content_layers)
style_targets = extractor(style)['style']
content_targets = extractor(content)['content']


In the paper, optimization was done using the L-BFGS algorithm, but you can use Adam also.
opt = tf.optimizers.Adam(learning_rate=0.02)

अब आइए समग्र कंटेंट और स्टाइल वेट्स तथा प्रत्येक स्टाइल निरूपण के वेट्स भी परिभाषित करें, जैसा पहले चर्चा की गई थी। ध्यान दें कि ये हाइपरपैरामीटर्स हैं और आपको इनके साथ प्रयोग करना चाहिए।

 # Custom weights for style and content updates
style_weight=100
content_weight=10

# Custom weights for different style layers
style_weights = {'block1_conv1': 1.,
                 'block2_conv1': 0.8,
                 'block3_conv1': 0.5,
                 'block4_conv1': 0.3,
                 'block5_conv1': 0.1}

अब आता है सबसे अहम हिस्सा, जो neural style transfer की प्रक्रिया को और भी रोचक बनाता है — लॉस फ़ंक्शन।

# The loss function to optimize
def total_loss(outputs):
    style_outputs = outputs['style']
    content_outputs = outputs['content']
    style_loss = tf.add_n([style_weights[name]*tf.reduce_mean((style_outputs[name]-style_targets[name])**2)
                           for name in style_outputs.keys()])
    # Normalize
    style_loss *= style_weight / num_style_layers

    content_loss = tf.add_n([tf.reduce_mean((content_outputs[name]-content_targets[name])**2)
                             for name in content_outputs.keys()])
    # Normalize
    content_loss *= content_weight / num_content_layers
    loss = style_loss + content_loss
    return loss

अब आप एक और फ़ंक्शन लिखेंगे जो:

  • आपके द्वारा अभी परिभाषित लॉस फ़ंक्शन के ग्रेडिएंट्स की गणना करेगा।
  • इन ग्रेडिएंट्स का उपयोग कर टारगेट इमेज को अपडेट करेगा।

GradientTape के साथ, आप स्वचालित अंतरकरण का लाभ उठा सकते हैं, जो किसी फ़ंक्शन के संघटन के आधार पर उसके ग्रेडिएंट्स की गणना कर सकता है। आप ऑपरेशन्स को तेज करने के लिए tf.function डेकोरेटर का भी उपयोग करेंगे। इसके बारे में अधिक पढ़ें यहाँ।

@tf.function()
def train_step(image):
  with tf.GradientTape() as tape:
    # Extract the features
    outputs = extractor(image)
    # Calculate the loss
    loss = total_loss(outputs)
  # Determine the gradients of the loss function w.r.t the image pixels
  grad = tape.gradient(loss, image)
  # Update the pixels
  opt.apply_gradients([(grad, image)])
  # Clip the pixel values that fall outside the range of [0,1]
  image.assign(tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=1.0))

नेटवर्क को ट्रेन करने से पहले एकमात्र शेष कदम टारगेट इमेज को परिभाषित करना है। टारगेट इमेज के लिए, आप कंटेंट इमेज का ही उपयोग करेंगे।

target_image = tf.Variable(content)

अब आप नेटवर्क को ट्रेन करने के लिए पूरी तरह तैयार हैं।

epochs = 10
steps_per_epoch = 100

step = 0
for n in range(epochs):
  for m in range(steps_per_epoch):
    step += 1
    train_step(target_image)
  plt.imshow(np.squeeze(target_image.read_value(), 0))
  plt.title("Train step: {}".format(step))
  plt.show()
WARNING: Logging before flag parsing goes to stderr.
W0617 16:21:34.491543 140709216896896 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1205: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where 

आपको टारगेट इमेज में होने वाले बदलावों को देखने के लिए कंटेंट और स्टाइल वेट्स के साथ प्रयोग करने की सलाह दी जाती है।

समापन टिप्पणी

जिस पेपर का आपने यहाँ ट्यूटोरियल में संदर्भ लिया, उसमें निर्मित छवि की गुणवत्ता को और बेहतर बनाने के बारे में उल्लेख नहीं था। जैसा कि आपने ऊपर के परिणामों में देखा होगा, निर्मित छवि के समग्र कंटेंट और स्टाइल के बीच स्थानिक संबंध में कुछ स्मूदनेस की आवश्यकता है। इस समस्या से निपटने के लिए, total_variantional_loss पेश किया गया, जो नियमन (regularization) के उपयोग के समान है। उच्च स्तर पर, total_variational_loss मूल neural style transfer एल्गोरिदम द्वारा उत्पन्न उच्च-आवृत्ति आर्टिफैक्ट्स को दंडित करता है। यदि आप इसे लागू करने में रुचि रखते हैं, तो यह ट्यूटोरियल देखें। निम्नलिखित कुछ संसाधन हैं जिनका उपयोग इस ट्यूटोरियल को लिखने में संदर्भ के रूप में किया गया:

यदि आप अपनी डीप लर्निंग स्किल्स को निखारना चाहते हैं, तो आप निम्नलिखित DataCamp कोर्सेज़ और ट्यूटोरियल्स देख सकते हैं:

विषय