<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Furkan Kınlı on Medium]]></title>
        <description><![CDATA[Stories by Furkan Kınlı on Medium]]></description>
        <link>https://medium.com/@birdortyedi_23820?source=rss-da685a287e6a------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*nTvD3MjoKwqAMTPH5DQ2Gw.jpeg</url>
            <title>Stories by Furkan Kınlı on Medium</title>
            <link>https://medium.com/@birdortyedi_23820?source=rss-da685a287e6a------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 19 May 2026 12:22:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@birdortyedi_23820/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[[Deep Learning Lab] Episode-5: CIFAR-100]]></title>
            <link>https://medium.com/@birdortyedi_23820/deep-learning-lab-episode-5-cifar-100-a557e19219ba?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/a557e19219ba</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[computer-vision]]></category>
            <category><![CDATA[cifar-100]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Mon, 03 Sep 2018 06:38:08 GMT</pubDate>
            <atom:updated>2019-03-15T17:38:23.880Z</atom:updated>
            <content:encoded><![CDATA[<p>Let the “Deep Learning Lab” begin!</p><p>This is the fifth episode of “Deep Learning Lab” story series which contains my individual deep learning works with different cases.</p><p>Previously on Deep Learning Lab:</p><ul><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-1-fashion-mnist-c7af60029836">Episode-1: Fashion-MNIST</a></li><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-2-cifar-10-631aea84f11e">Episode-2: CIFAR-10</a></li><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-3-fer2013-c38f2e052280">Episode-3: fer2013</a></li><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-4-deep-fashion-2df9e15a63e1">Episode-4: Deep Fashion</a></li></ul><p>As I already mentioned in Episode 2, I would like to work on CIFAR-100 which contains 60.000 different images with 100 categories for this episode. The main aim in this work will be to reach or exceed.. Sorry. Mmm... Actually, to try to show how the model which has the best score in the literature is implemented. I’m sure that it will be exciting to re-implement <a href="https://arxiv.org/pdf/1511.07289.pdf">the article “Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)”</a> which explains how to invent ELUs and how it works by comparison with ReLUs and its newfangled versions (sReLUs, LReLUs etc.) by <a href="https://arxiv.org/search/cs?searchtype=author&amp;query=Clevert%2C+D">Djork-Arné Clevert</a>, <a href="https://arxiv.org/search/cs?searchtype=author&amp;query=Unterthiner%2C+T">Thomas Unterthiner</a>, <a href="https://arxiv.org/search/cs?searchtype=author&amp;query=Hochreiter%2C+S">Sepp Hochreiter</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/356/1*fTQtXyApxWPoW2vzSEk_Pw.png" /><figcaption>CIFAR-100</figcaption></figure><p>Please let me quickly remind you what CIFAR data sets are. CIFAR data sets are one of the most well-known data sets in computer vision tasks created by Geoffrey Hinton, Alex Krizhevsky and Vinod Nair. While CIFAR-10 is more popular to start to work on deep learning from scratch since it has 10 category labels for the images, however, to work with CIFAR-100 is not a common behavior in deep learning community since it is not easy to train a -really- deep learning model. There are 100 different category labels containing 600 images for each (1 testing image for 5 training images per class). The 100 classes in the CIFAR-100 are grouped into 20 super-classes. Each image comes with a “fine” label (the class to which it belongs) and a “coarse” label (the super-class to which it belongs). We will work with the fine labels.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/799/1*iI_Wzaif4tML9jZkRNKPWA.png" /><figcaption>CIFAR-100 Class List</figcaption></figure><p>Moreover, it is not possible to get results (above 90%) such like in MNIST-like data sets, then bloggers or tutorial writers do not prefer to use CIFAR-100 -broadly speaking-, since they are aware of not making the readers feel like they change the world. -But, I do-.</p><p>Let me reference to the real hero:</p><blockquote>Learning Multiple Layers of Features from Tiny Images, Alex Krizhevsky, 2009</blockquote><blockquote><a href="https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf">University of Toronto, Technical Report</a></blockquote><p>In this episode, I will re-implement the article of <a href="https://arxiv.org/search/cs?searchtype=author&amp;query=Clevert%2C+D">Djork-Arné Clevert</a>, <a href="https://arxiv.org/search/cs?searchtype=author&amp;query=Unterthiner%2C+T">Thomas Unterthiner</a>, <a href="https://arxiv.org/search/cs?searchtype=author&amp;query=Hochreiter%2C+S">Sepp Hochreiter</a> about discussing a new activation function approach. They claimed that using ELUs as activation function evokes getting more accurate results in faster way. How the activation function runs faster is not our main concern, so I strongly suggest you to read <a href="https://arxiv.org/pdf/1511.07289.pdf">the article</a> if you want to get more information about it.</p><p>The main problem -according to the article- in ReLUs is that their mean activation is not zero. In the other words, ReLUs are not zero-centered activation functions and it leads to shift the bias term for the term in the next layer. But then, ELUs arranges the mean of the activation closer to zero because they have negative values, even if these values are very close to zero, and it converges faster, -it means the model will learn faster-.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/485/1*gTKAjWW2JRdgkxX_tvzL7A.png" /><figcaption>ELU vs. ReLUs</figcaption></figure><p>The magic behind ELUs is surprisingly easy to see. ELUs have exponential term in the formula and the derivative of an exponential term, as you all know, equals to the exponential term itself. For the forward propagation, all weights and biases are activated with some constant multiplication of an exponential of them, and they are back-propagated with the derivative of the activation function, it is -actually- exponential of all weights and biases. The formula can be seen below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/558/1*5525BQ-V20xIjsCZ9uHz0g.png" /><figcaption>The formula of ELUs and the derivative of ELUs</figcaption></figure><p>It seems that it works very well with CIFAR-100 data sets, since they have the best accuracy score in the literature, -for now-. I prefer to save the benchmark scores for the last.</p><p>Let me reference to the other real heroes:</p><blockquote>Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs), Djork-Arné Clevert, Thomas Unterthiner, Sepp Hochreiter, 2016</blockquote><blockquote><a href="https://arxiv.org/pdf/1511.07289.pdf">International Conference on Learning Representations (ICLR) 2016</a></blockquote><p>No more speaking. We have too much jobs to do here. It is the time for coding.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FWWIdmxmpNpwys%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FWWIdmxmpNpwys%2Fgiphy.gif&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FWWIdmxmpNpwys%2F200.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="317" frameborder="0" scrolling="no"><a href="https://medium.com/media/dbdfb736773e0b1da53cf446f64f10d3/href">https://medium.com/media/dbdfb736773e0b1da53cf446f64f10d3/href</a></iframe><p><strong>LET’S GOOOOO!</strong></p><p>At this point, I would like to convey my thanks to MSI Turkey and Tufan Vardar, Digital Marketing Specialist @ MSI Turkey since they donated one 1080Ti GPU to me to foster my academic researches and blog posts.</p><p>Importing the libraries as we always do.</p><pre>from __future__ import print_function<br>import keras<br>from keras.datasets import cifar100<br>from keras.models import Sequential<br>from keras.layers import Dense, Dropout, Activation, Flatten<br>from keras.layers import Conv2D, MaxPooling2D, ZeroPadding2D<br>from keras.optimizers import SGD<br>from keras.regularizers import l2<br>from keras.callbacks import Callback, LearningRateScheduler, TensorBoard, ModelCheckpoint<br>from keras.preprocessing.image import ImageDataGenerator<br>from keras.utils import print_summary, to_categorical<br>from keras import backend as K<br>import sys<br>import os<br>import numpy as np</pre><p>Initializing the parameters. In section 4.3 of the article, the parameters have been described.</p><ul><li>Mini batch size: 100</li><li>Initial learning rate: 0.01</li><li>Momentum rate: 0.9</li><li>L2 regularization weight decay: 0.0005</li><li>Dropout rates for all layers: 0.5.</li></ul><pre>BATCH_SIZE = 100<br>NUM_CLASSES = 100<br>EPOCHS = 165000<br>INIT_DROPOUT_RATE = 0.5<br>MOMENTUM_RATE = 0.9<br>INIT_LEARNING_RATE = 0.01<br>L2_DECAY_RATE = 0.0005<br>CROP_SIZE = 32<br>LOG_DIR = ‘./logs’<br>MODEL_PATH = ‘./models/keras_cifar100_model.h5’</pre><p>Thanks to Keras, we can load the data set easily.</p><pre>(x_train, y_train), (x_test, y_test) = cifar100.load_data()</pre><p>We need to convert the labels in the data set into categorical matrix structure from 1-dim numpy array structure.</p><pre>y_train = to_categorical(y_train, NUM_CLASSES)<br>y_test = to_categorical(y_test, NUM_CLASSES)</pre><p>We need to normalize the images in the data set.</p><pre>x_train = x_train.astype(‘float32’)<br>x_test = x_test.astype(‘float32’)<br>x_train /= 255.0<br>x_test /= 255.0</pre><p>(From the article) The data set should be preprocessed with global contrast normalization (sample-wise centering) and ZCA whitening. Additionally, the images should be padded with four 0 pixels at all borders (2D zero padding layer at the top of the model). The model should be trained 32x32 random crops with random horizontal flipping. That’s all for data augmentation.</p><p>The CNN Architecture:</p><p>18 convolutional layers arranged in stacks of</p><p>(layers x units x receptive fields)</p><p>([1×384×3],[1×384×1,1×384×2,2×640×2],[1×640×1,3×768×2],[1×768×1,2×896×2],[1×896×3,2×1024×2],[1×1024×1,1×1152×2],[1×1152×1],[1×100×1])</p><pre>model = Sequential()<br>model.add(ZeroPadding2D(4, input_shape=x_train.shape[1:]))<br># Stack 1:<br>model.add(Conv2D(384, (3, 3), padding=&#39;same&#39;, kernel_regularizer=l2(0.01)))<br>model.add(Activation(&#39;elu&#39;))<br>model.add(MaxPooling2D(pool_size=(2, 2), padding=&#39;same&#39;))<br>model.add(Dropout(INIT_DROPOUT_RATE))</pre><pre># Stack 2:<br>model.add(Conv2D(384, (1, 1), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(384, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(640, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(640, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Activation(&#39;elu&#39;))<br>model.add(MaxPooling2D(pool_size=(2, 2), padding=&#39;same&#39;))<br>model.add(Dropout(INIT_DROPOUT_RATE))</pre><pre># Stack 3:<br>model.add(Conv2D(640, (3, 3), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(768, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(768, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(768, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Activation(&#39;elu&#39;))<br>model.add(MaxPooling2D(pool_size=(2, 2), padding=&#39;same&#39;))<br>model.add(Dropout(INIT_DROPOUT_RATE))</pre><pre># Stack 4:<br>model.add(Conv2D(768, (1, 1), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(896, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(896, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Activation(&#39;elu&#39;))<br>model.add(MaxPooling2D(pool_size=(2, 2), padding=&#39;same&#39;))<br>model.add(Dropout(INIT_DROPOUT_RATE))</pre><pre># Stack 5:<br>model.add(Conv2D(896, (3, 3), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(1024, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(1024, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Activation(&#39;elu&#39;))<br>model.add(MaxPooling2D(pool_size=(2, 2), padding=&#39;same&#39;))<br>model.add(Dropout(INIT_DROPOUT_RATE))</pre><pre># Stack 6:<br>model.add(Conv2D(1024, (1, 1), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Conv2D(1152, (2, 2), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Activation(&#39;elu&#39;))<br>model.add(MaxPooling2D(pool_size=(2, 2), padding=&#39;same&#39;))<br>model.add(Dropout(INIT_DROPOUT_RATE))</pre><pre># Stack 7:<br>model.add(Conv2D(1152, (1, 1), padding=&#39;same&#39;, kernel_regularizer=l2(L2_DECAY_RATE)))<br>model.add(Activation(&#39;elu&#39;))<br>model.add(MaxPooling2D(pool_size=(2, 2), padding=&#39;same&#39;))<br>model.add(Dropout(INIT_DROPOUT_RATE))</pre><pre>model.add(Flatten())<br>model.add(Dense(NUM_CLASSES))<br>model.add(Activation(&#39;softmax&#39;))</pre><p>This network is very deep. Very. With my resources, one epoch runs on 3 minutes. If we want to experiment this article completely, we have to train the model for 165.000 epoch. It means the training needs to at least 40 days -nonstop- to run.</p><p>This is insane.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FmQC0dMQwoQ4Fy%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FmQC0dMQwoQ4Fy%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FmQC0dMQwoQ4Fy%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/4a079752f8eb128bce01548c803db4c4/href">https://medium.com/media/4a079752f8eb128bce01548c803db4c4/href</a></iframe><p>You can check the summary of model how much the model is deep.</p><pre>model.summary()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/548/1*2Ny2SsHPHQAe6_J071nXmA.png" /><figcaption>Summary of the model (tail)</figcaption></figure><p>Other adjustments to the model:</p><ul><li>The learning rate will be decreased by a factor of 10 after 35.000 iterations</li><li>For the later 50.000 iterations, the drop-out rate will be increased for all layers in a stack to (0, 0.1, 0.2, 0.3, 0.4, 0.5, 0).</li><li>For the last 40.000 iterations, the drop-out rate will be increased by a factor of 1.5 for all layers.</li></ul><p>We need to use callbacks to make these adjustments. First, we will write the schedulers for learning rate and the drop-out rate.</p><p>For the learning rate:</p><pre>def lr_scheduler(epoch, lr, step_decay = 0.1):<br>    return float(lr * step_decay) if epoch == 35.000 else lr</pre><p>For the drop-out rate:</p><pre>def dr_scheduler(epoch, layers, rate_list = [0.0, .1, .2, .3, .4, .5, 0.0], rate_factor = 1.5):<br>    if epoch == 85000:<br>        for i, layer in enumerate([l for l in layers if &quot;dropout&quot; in np.str.lower(l.name)]):<br>            layer.rate = layer.rate + rate_list[i]<br>    elif epoch == 135000:<br>        for i, layer in enumerate([l for l in layers if &quot;dropout&quot; in np.str.lower(l.name)]):<br>            layer.rate = layer.rate + layer.rate * rate_factor if layer.rate &lt;= 0.66 else 1<br>    return layers</pre><p>Then, we can define our custom callback objects for the learning rate</p><pre>class StepLearningRateSchedulerAt(LearningRateScheduler):<br>    def __init__(self, schedule, verbose = 0): <br>        super(LearningRateScheduler, self).__init__()<br>        self.schedule = schedule<br>        self.verbose = verbose<br>    <br>    def on_epoch_begin(self, epoch, logs=None): <br>        if not hasattr(self.model.optimizer, &#39;lr&#39;):<br>            raise ValueError(&#39;Optimizer must have a &quot;lr&quot; attribute.&#39;)<br>            <br>        lr = float(K.get_value(self.model.optimizer.lr))<br>        lr = self.schedule(epoch, lr)<br>       <br>        if not isinstance(lr, (float, np.float32, np.float64)):<br>            raise ValueError(&#39;The output of the &quot;schedule&quot; function &#39; &#39;should be float.&#39;)<br>        <br>        K.set_value(self.model.optimizer.lr, lr)</pre><pre>        if self.verbose &gt; 0: <br>            print(&#39;\nEpoch %05d: LearningRateScheduler reducing learning &#39; &#39;rate to %s.&#39; % (epoch + 1, lr))</pre><p>and the drop-out rate.</p><pre>class DropoutRateScheduler(Callback):<br>    def __init__(self, schedule, verbose = 0):<br>        super(Callback, self).__init__()<br>        self.schedule = schedule<br>        self.verbose = verbose<br>        <br>    def on_epoch_begin(self, epoch, logs=None):<br>        if not hasattr(self.model, &#39;layers&#39;):<br>            raise ValueError(&#39;Model must have a &quot;layers&quot; attribute.&#39;)<br>            <br>        layers = self.model.layers<br>        layers = self.schedule(epoch, layers)<br>        <br>        if not isinstance(layers, list):<br>            raise ValueError(&#39;The output of the &quot;schedule&quot; function should be list.&#39;)<br>        <br>        self.model.layers = layers<br>        <br>        if self.verbose &gt; 0:<br>            for layer in [l for l in self.model.layers if &quot;dropout&quot; in np.str.lower(l.name)]:<br>                print(&#39;\nEpoch %05d: Dropout rate for layer %s: %s.&#39; % (epoch + 1, layer.name, layer.rate))</pre><p>Let’s get back to the data augmentation methods. By applying zero padding four 0 pixels at all borders, we will randomly crop the images by 32x32. To achieve this, we need to create custom generator which takes ImageDataGenerator object as an input and yields each batch of images by cropping them. <a href="https://jkjung-avt.github.io/keras-image-cropping/">Source: JK Jung’s Blog</a></p><p>First, create a method to crop an image with a certain size.</p><pre>def random_crop(img, random_crop_size):<br>    height, width = img.shape[0], img.shape[1]<br>    dy, dx = random_crop_size<br>    x = np.random.randint(0, width - dx + 1)<br>    y = np.random.randint(0, height - dy + 1)<br>    return img[y:(y+dy), x:(x+dx), :]</pre><p>Then, apply this method to each image in the batch which yields from ImageDataGenerator object.</p><pre>def crop_generator(batches, crop_length, num_channel = 3):<br>    while True:<br>        batch_x, batch_y = next(batches)<br>        batch_crops = np.zeros((batch_x.shape[0], crop_length, crop_length, num_channel))<br>        for i in range(batch_x.shape[0]):<br>            batch_crops[i] = random_crop(batch_x[i], (crop_length, crop_length))<br>        yield (batch_crops, batch_y)</pre><p>Clevert and his colleagues preferred to use the Stochastic Gradient Descent with Momentum algorithm to optimize the weights on the back-propagation. Momentum term has been set to 0.9, and Nesterov accelerator for SGD has not been used. I, again, strongly recommend you to read an article, <a href="http://leon.bottou.org/publications/pdf/compstat-2010.pdf">this one</a> and <a href="https://arxiv.org/pdf/1609.04747.pdf">this one</a>, in order to get more information about SGD algorithm.</p><pre>opt = SGD(lr=INIT_LEARNING_RATE, momentum=MOMENTUM_RATE)</pre><p>Here is the part that I be loved. Callbacks! Let’s create callback objects. First one is our custom learning scheduler to decrease the learning rate after a certain number of epoch. Also, we have another custom callback for adjusting the drop-out rates in the stack layers. Next, we will record what our model has done during the training process. And lastly, we will save our trained model in each epoch that has better result than previous one.</p><p>(Please do not forget to call them by fitting the data to the generator, I forgot the drop-out scheduler, and I spent one day to realize that I -actually- do not call it. That was one of the most painful experience in my deep learning life.)</p><pre>lr_rate_scheduler = StepLearningRateSchedulerAt(lr_scheduler)<br>dropout_scheduler = DropoutRateScheduler(dr_scheduler)<br>tensorboard = TensorBoard(log_dir=LOG_DIR, batch_size=BATCH_SIZE)<br>checkpointer = ModelCheckpoint(MODEL_PATH, monitor=&#39;val_loss&#39;, verbose=1, save_best_only=True)</pre><p>That’s all I think. Now, we are ready to compile our model. Categorical cross-entropy has been picked as loss function since we have 100 category labels in the data set, and we already prepared the labels in the categorical matrix structure. Likewise, we will measure our performance on the validation set with top-1 and top-5 accuracies.</p><pre>model.compile(optimizer=opt,<br>              loss=&#39;categorical_crossentropy&#39;,<br>              metrics=[&#39;accuracy&#39;, &#39;top_k_categorical_accuracy&#39;])</pre><p>We will use ImageDataGenerator object to handle the data pre-processing on real time and make sure that the process goes randomly. Just for reminding, in the article, global contrast normalization (sample-wise centering) and ZCA whitening and horizontal flipping methods should be used for augmenting the data.</p><pre>datagen = ImageDataGenerator(samplewise_center=True,<br>                             zca_whitening=True,<br>                             horizontal_flip=True,<br>                             validation_split=0.2)</pre><p>ATTENTION!</p><p>If we use sample-wise or feature-wise centering methods, we have to fit the training data to the generator. Otherwise, these methods do not work.</p><pre>datagen.fit(x_train)</pre><p>Now, we will flow the data using our custom generator object for cropping the images. Here is the flowing methods for training and validation data. Since we define the rate of splitting the data to training and validation in the ImageDataGenerator object, it is enough to specify the subset as “training” or “validation” in the flowing method to split the data.</p><pre>train_flow = datagen.flow(x_train, y_train, batch_size=BATCH_SIZE, subset=&quot;training&quot;)<br>train_flow_w_crops = crop_generator(train_flow, CROP_SIZE)<br>valid_flow = datagen.flow(x_train, y_train, batch_size=BATCH_SIZE, subset=&quot;validation&quot;)</pre><p>WOW! Ready to train, huh?</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl2Sqc3POpzkj5r8SQ%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fl2Sqc3POpzkj5r8SQ%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2Fl2Sqc3POpzkj5r8SQ%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="182" frameborder="0" scrolling="no"><a href="https://medium.com/media/72c1019228a59de12ba27897b37f17a9/href">https://medium.com/media/72c1019228a59de12ba27897b37f17a9/href</a></iframe><p><strong>GO GO GO!!!</strong></p><pre>model.fit_generator(train_flow_w_crops,<br>                    epochs=EPOCHS,<br>                    steps_per_epoch=len(x_train) / BATCH_SIZE,<br>                    callbacks=[lr_rate_scheduler, dropout_scheduler, tensorboard, checkpointer],<br>                    validation_data=valid_flow,<br>                    validation_steps=len(x_train) / BATCH_SIZE)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/984/1*0yhQPAZuAxK2twwJfMXjUQ.png" /><figcaption>Head of epochs</figcaption></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl0G18gptStsYQrcL6%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fl0G18gptStsYQrcL6%2Fgiphy.gif&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fl0G18gptStsYQrcL6%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="333" frameborder="0" scrolling="no"><a href="https://medium.com/media/eca6a6aab241ee7c78a979f46e9696d4/href">https://medium.com/media/eca6a6aab241ee7c78a979f46e9696d4/href</a></iframe><p>165.000 epochs! COME ON!</p><p>As I mentioned earlier, I cannot finish the training process with my resources (by the way, it is 1080Ti). So, we do not have model to test at the end of this episode. If you have better GPU/s and have never ending patient during the training (for me it was expected to run at least 40 days -nonstop-), you can go for it -but I won’t-.</p><pre>test_datagen = ImageDataGenerator(samplewise_center=True,<br>                                  zca_whitening=True)<br>test_datagen.fit(x_test)</pre><pre>test_flow = test_datagen.flow(x_test, y_test, batch_size=BATCH_SIZE)<br>results = model.evaluate_generator(test_flow, steps=len(x_test) / BATCH_SIZE)</pre><pre>print(&#39;Test loss: &#39; + str(results[0]))<br>print(&#39;Accuracy: &#39; + str(results[1]))<br>print(&#39;Top-5 Accuracy: &#39; + str(results[2]))</pre><p>Here is the results of this model in the article.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/550/1*Ds_ZyviJLk3IObeu5hb91A.png" /><figcaption>Results of this model on CIFAR data sets</figcaption></figure><p>As you can see, the top-1 accuracy of this model on CIFAR-100 is 75.72%. This is the best result in the literature. For the details of the experiment, please read the article.</p><p>You can find the Jupyter Notebook of this episode in my <a href="https://github.com/birdortyedi/deeplearninglab">GitHub Repository</a>.</p><p>Well, the fifth episode of “Deep Learning Lab” series, CIFAR-100 ends here. Thank you for taking the time with me. For comments and suggestions, please <a href="mailto:furkan.kinli@ozu.edu.tr">e-mail</a> me. You can also contact me via <a href="https://www.linkedin.com/in/furkan-kınlı-4b5648116/">LinkedIn</a>. Thank you.</p><p>fk.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a557e19219ba" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[[Deep Learning Lab] Episode-4: Deep Fashion]]></title>
            <link>https://medium.com/@birdortyedi_23820/deep-learning-lab-episode-4-deep-fashion-2df9e15a63e1?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/2df9e15a63e1</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[object-detection]]></category>
            <category><![CDATA[transfer-learning]]></category>
            <category><![CDATA[keras]]></category>
            <category><![CDATA[deep-learning]]></category>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Wed, 27 Jun 2018 06:01:01 GMT</pubDate>
            <atom:updated>2019-03-15T17:37:44.417Z</atom:updated>
            <content:encoded><![CDATA[<p>Let the “Deep Learning Lab” begin!</p><p>This is the fourth episode of “Deep Learning Lab” story series which contains my individual deep learning works with different cases.</p><p>Previously on Deep Learning Lab:</p><ul><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-1-fashion-mnist-c7af60029836">Episode-1: Fashion-MNIST</a></li><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-2-cifar-10-631aea84f11e">Episode-2: CIFAR-10</a></li><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-3-fer2013-c38f2e052280">Episode-3: fer2013</a></li></ul><p>In this episode, I will be appreciated to introduce DeepFashion dataset, which is a large-scale clothes database and has several appealing properties, to deep learning enthusiasts -I mean, you-</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I4ms0TJisKebAxMlRiZvpQ.jpeg" /><figcaption>Clip art of DeepFashion dataset</figcaption></figure><p>Let’s quickly give more information about the DeepFashion dataset. DeepFashion is an open-source (commercial use not allowed by release agreement) dataset which is created for IEEE Conference on Computer Vision and Pattern Recognition (CVPR) in 2016 by Ziwei Liu, Ping Luo and their colleagues in The Chinese University of Hong-Kong and Shenzhen Institutes of Advanced Technology.</p><p>This dataset consists of more than 800.000 different RGB-colored images -ranging from well-posed shopping images to unstructured customer images &amp; cross-posed and cross-domain images-. The size of images are not same as in the other well-known datasets and each image in the dataset is labeled with one of ~50 categories, ~1000 attributes, bounding box and clothing landmarks. In this work, I just focused on category classification and bounding box detection tasks using such a large subset (~290.000 images) of this well-prepared dataset which contains clothing categories and attributes in wild.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*toypAMKChmQn3-XizfbkBA.jpeg" /><figcaption>Example of categories and attributes</figcaption></figure><p>Let me reference to the real heroes:</p><blockquote>DeepFashion: Powering Robust Clothes Recognition and Retrievel with Rich Annotations, Ziwei Liu et al., 2016</blockquote><blockquote><a href="https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Liu_DeepFashion_Powering_Robust_CVPR_2016_paper.pdf">Proceedings of IEEE Conference on Computer Vision and Pattern Recognition (CVPR) 2016</a></blockquote><p><strong>ARE WE READY TO THIS JOURNEY?</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FDiz6gTxk2qipq%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FDiz6gTxk2qipq%2Fgiphy.gif&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FDiz6gTxk2qipq%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="261" frameborder="0" scrolling="no"><a href="https://medium.com/media/96b782e7a94df9b1a6f34347a466ba03/href">https://medium.com/media/96b782e7a94df9b1a6f34347a466ba03/href</a></iframe><p><strong>LET’S GOOOO!!!</strong></p><p>After downloading the dataset from <a href="http://mmlab.ie.cuhk.edu.hk/projects/DeepFashion/AttributePrediction.html">here</a>, we need to prepare the category labels by adding images to folders as images with same label in the same folder. Besides, we need to split the data into train, validation and test sets as annotated in the paper. But first, importing the libraries -please-.</p><pre>import shutil<br>import os<br>import re<br>import cv2</pre><pre># will use them for creating custom directory iterator<br>import numpy as np<br>from six.moves import range</pre><pre># regular expression for splitting by whitespace<br>splitter = re.compile(&quot;\s+&quot;)<br>base_path = &#39;&lt;FOLDER_OF_IMAGES_THAT_YOU_DOWNLOADED&gt;&#39;</pre><p>Then,</p><pre>def process_folders():<br>    # Read the relevant annotation file and preprocess it<br>    # Assumed that the annotation files are under &#39;&lt;project folder&gt;/data/anno&#39; path<br>    with open(&#39;./data/anno/list_eval_partition.txt&#39;, &#39;r&#39;) as eval_partition_file:<br>        list_eval_partition = [line.rstrip(&#39;\n&#39;) for line in eval_partition_file][2:]<br>        list_eval_partition = [splitter.split(line) for line in list_eval_partition]<br>        list_all = [(v[0][4:], v[0].split(&#39;/&#39;)[1].split(&#39;_&#39;)[-1], v[1]) for v in list_eval_partition]<br><br>    # Put each image into the relevant folder in train/test/validation folder<br>    for element in list_all:<br>        if not os.path.exists(os.path.join(base_path, element[2])):<br>            os.mkdir(os.path.join(base_path, element[2]))<br>        if not os.path.exists(os.path.join(os.path.join(base_path, element[2]), element[1])):<br>            os.mkdir(os.path.join(os.path.join(base_path, element[2]), element[1]))<br>        if not os.path.exists(os.path.join(os.path.join(os.path.join(os.path.join(base_path, element[2]), element[1])),<br>                              element[0].split(&#39;/&#39;)[0])):<br>            os.mkdir(os.path.join(os.path.join(os.path.join(os.path.join(base_path, element[2]), element[1])),<br>                     element[0].split(&#39;/&#39;)[0]))<br>        shutil.move(os.path.join(base_path, element[0]),<br>                    os.path.join(os.path.join(os.path.join(base_path, element[2]), element[1]), element[0])</pre><pre>process_folders()</pre><p>We need to extract the bounding box information from the annotation file and to normalize the values of bounding box information by the shape of the related image.</p><pre>def create_dict_bboxes(list_all, split=&#39;train&#39;):<br>    lst = [(line[0], line[1], line[3], line[2]) for line in list_all if line[2] == split]<br>    lst = [(&quot;&quot;.join(line[0].split(&#39;/&#39;)[0] + &#39;/&#39; + line[3] + &#39;/&#39; + line[1] + line[0][3:]), line[1], line[2]) for line in lst]<br>    lst_shape = [cv2.imread(&#39;./data/&#39; + line[0]).shape for line in lst]<br>    lst = [(line[0], line[1], (round(line[2][0] / shape[1], 2), round(line[2][1] / shape[0], 2), round(line[2][2] / shape[1], 2), round(line[2][3] / shape[0], 2))) for line, shape in zip(lst, lst_shape)]<br>    dict_ = {&quot;/&quot;.join(line[0].split(&#39;/&#39;)[2:]): {&#39;x1&#39;: line[2][0], &#39;y1&#39;: line[2][1], &#39;x2&#39;: line[2][2], &#39;y2&#39;: line[2][3], &#39;shape&#39;: line[2][4]} for line in lst}<br>    return dict_</pre><pre>def get_dict_bboxes():<br>    with open(&#39;./data/anno/list_category_img.txt&#39;, &#39;r&#39;) as category_img_file, \<br>            open(&#39;./data/anno/list_eval_partition.txt&#39;, &#39;r&#39;) as eval_partition_file, \<br>            open(&#39;./data/anno/list_bbox.txt&#39;, &#39;r&#39;) as bbox_file:<br>        list_category_img = [line.rstrip(&#39;\n&#39;) for line in category_img_file][2:]<br>        list_eval_partition = [line.rstrip(&#39;\n&#39;) for line in eval_partition_file][2:]<br>        list_bbox = [line.rstrip(&#39;\n&#39;) for line in bbox_file][2:]<br><br>        list_category_img = [splitter.split(line) for line in list_category_img]<br>        list_eval_partition = [splitter.split(line) for line in list_eval_partition]<br>        list_bbox = [splitter.split(line) for line in list_bbox]<br><br>        list_all = [(k[0], k[0].split(&#39;/&#39;)[1].split(&#39;_&#39;)[-1], v[1], (int(b[1]), int(b[2]), int(b[3]), int(b[4])))<br>                    for k, v, b in zip(list_category_img, list_eval_partition, list_bbox)]<br><br>        list_all.sort(key=lambda x: x[1])<br><br>        dict_train = create_dict_bboxes(list_all)<br>        dict_val = create_dict_bboxes(list_all, split=&#39;val&#39;)<br>        dict_test = create_dict_bboxes(list_all, split=&#39;test&#39;)<br><br>        return dict_train, dict_val, dict_test</pre><p>Too much work for preprocessing, huh?…</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FeNTxLwTGW7E64%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FeNTxLwTGW7E64%2Fgiphy.gif&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FeNTxLwTGW7E64%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="326" frameborder="0" scrolling="no"><a href="https://medium.com/media/d09adbabd84b39e843f9b82c2da34f05/href">https://medium.com/media/d09adbabd84b39e843f9b82c2da34f05/href</a></iframe><p>And now, we can import Keras-things.</p><pre>from keras.models import Model<br>from keras.layers import Dense<br>from keras.regularizers import l2<br>from keras.optimizers import SGD<br>from keras.applications.resnet50 import ResNet50<br>from keras.preprocessing import image<br>from keras.preprocessing.image import DirectoryIterator, ImageDataGenerator<br>from keras.callbacks import ReduceLROnPlateau, ModelCheckpoint, EarlyStopping, TensorBoard<br>from keras import backend as K</pre><p>We have to be aware of that this dataset contains ~290.000 images. It is not possible to train a ‘deep’ learning model from scratch even if you have a sup-computer -not super :)- with 32 GB RAM and 1080 Ti GPU.</p><blockquote><strong>How do we solve this problem?</strong></blockquote><p>I can hear you.</p><p>Yes. Transfer learning.</p><p>Well, transfer learning is a general machine learning method where a developed model for a general task is reused for more specific task as a starting point. This is too much simple definition of transfer learning. Please look at these links for more information about transfer learning: <a href="https://machinelearningmastery.com/transfer-learning-for-deep-learning/">A Gentle Introduction to Transfer Learning for Deep Learning</a> &amp; <a href="http://cs231n.github.io/transfer-learning/">CS231n Convolutional Neural Networks for Visual Recognition</a></p><p>In our case, we will use 50-layer residual network (ResNet50) model pre-trained with ImageNet, but we will not train all layers in this model from scratch. After freezing the earlier layers which represent low-level features as weights such as line detector and pattern detector, we will train the layers which represent higher level features -more specific to data- by optimizing the loss function with low learning rate.</p><ul><li>Less parameters to train</li><li>Less time for training</li><li>Preserving the lower level feature weights while fine-tuning the data-specific feature weights</li><li>Eliminating the possibility of getting stucked on local minima for the loss function during the early stage of the training</li></ul><p>Just write this code snippet to get pre-trained ResNet50 model in Keras.</p><pre>model_resnet = ResNet50(weights=&#39;imagenet&#39;, include_top=False, pooling=&#39;avg&#39;)</pre><blockquote><strong>Not including at top?? What does that mean?</strong></blockquote><p>For ImageNet dataset, there are different 1000 labels to categorize the images. Thus, when you want to train a model with ImageNet dataset, you need to specify the number of neurons in the output (softmax) layer as 1000. However, we have such a dataset with ~50 -actually, 46- labels to categorize the images. We should not include the top (output, softmax, last, whatever you would like to call) layer of ResNet50 for our model, so we can add a new layer and specify the number of neurons as what the dataset needs.</p><p>As I mentioned before, we need to freeze some layers in the very first part of the model. Freezing a layer means that -simply- making it not trainable in the model.</p><pre>for layer in model_resnet.layers[:-12]:<br>    # 6 - 12 - 18 have been tried. 12 is the best.<br>    layer.trainable = False</pre><p>Now, let’s build the category classification branch in the model.</p><pre>x = model_resnet.output<br>x = Dense(512, activation=&#39;elu&#39;, kernel_regularizer=l2(0.001))(x)<br>y = Dense(46, activation=&#39;softmax&#39;, name=&#39;img&#39;)(x)</pre><p>Then, we will build the bounding box detection branch in the model.</p><pre>x_bbox = model_resnet.output<br>x_bbox = Dense(512, activation=&#39;relu&#39;, kernel_regularizer=l2(0.001))(x_bbox)<br>x_bbox = Dense(128, activation=&#39;relu&#39;, kernel_regularizer=l2(0.001))(x_bbox)<br>bbox = Dense(4, kernel_initializer=&#39;normal&#39;, name=&#39;bbox&#39;)(x_bbox)</pre><p>Finally, we will create our final model by specifying the input and outputs for the branches.</p><pre>final_model = Model(inputs=model_resnet.input,<br>                    outputs=[y, bbox])</pre><p>The summary of our transfer learning model could be seen as:</p><pre>print(final_model.summary())</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/806/1*q2Sr9HZF3HYouxyWRJpw0w.png" /><figcaption>The summary of trainable part of our transfer learning model</figcaption></figure><p>It could be seen that the number of trainable parameters in our custom ResNet50-like model are almost 25% percent of total number of parameters in original ResNet50 since we have already frozen the bunch of layers that contains low-level feature information and we will be training just last 12 layers.</p><p>To train a transfer learning model is hard to optimize. I am -still- working on how the optimization methods effect the training process and loss function for transfer learning approach. I will use Stochastic Gradient Descent (SGD) algorithm to optimize the weights in the backpropagation in order to make sure that I am on the safe side. Set the momentum parameter as 0.9 and the nesterov parameter as True. I strongly recommend you to read an article, <a href="http://leon.bottou.org/publications/pdf/compstat-2010.pdf">this one</a>, to get more information about SGD algorithm.</p><pre>opt = SGD(lr=0.0001, momentum=0.9, nesterov=True)</pre><blockquote><strong>Why do we keep the learning rate too low?</strong></blockquote><p>The answer is simple. We want to not change the weights by destroying the information coming from the ImageNet and to learn something from the data. If you use default learning value, for example, the loss function will converge too fast and start to over-fit the training set.</p><p>We are ready now to compile our model. While categorical crossentropy method has been picked as loss function for category classification task, mean squared error method has been picked as loss function for bounding box detection task -you can pick either mean squarred logarithmic error-. Likewise, we will measure our performance on the validation set with top-1 and top-5 accuracies for category classification, and mean squarred error for bounding box detection.</p><pre>final_model.compile(optimizer=opt,<br>                    loss={&#39;img&#39;: &#39;categorical_crossentropy&#39;,<br>                          &#39;bbox&#39;: &#39;mean_squared_error&#39;},<br>                    metrics={&#39;img&#39;: [&#39;accuracy&#39;, &#39;top_k_categorical_accuracy&#39;], # default: top-5<br>                             &#39;bbox&#39;: [&#39;mse&#39;]})</pre><p>We have some problems here. How do we load our data without being out of bounds for memory? Also, how do we give such an input which contains an image, category label and bounding box together? Let’s figure it out!</p><ul><li><strong>Loading the data:</strong></li></ul><p>If you try to load all images with at least 100x100 size to your less than 64 GB memory, it will be out of bounds for memory. The solution is flowing the images as a batch from the directory -ImageDataGenerator class in Keras-, it will load the data and give it to the model as batch-to-batch. Besides, we can augment the data in real time by helping of this method. At the end, we need to create ImageDataGenerator objects for training and test sets.</p><pre>train_datagen = ImageDataGenerator(rotation_range=30.,<br>                                   shear_range=0.2,<br>                                   zoom_range=0.2,<br>                                   width_shift_range=0.2,<br>                                   height_shift_range=0.2,<br>                                   horizontal_flip=True)<br>test_datagen = ImageDataGenerator()</pre><p>Note that if you use normalization methods (feature-wise/sample-wise std normalization) to augment the data, you have to fit and transform the data before starting to train the data.</p><ul><li><strong>Manipulating the batch iterator:</strong></li></ul><p>This part could be seen as the most challenging part of this episode, but actually it is not. In ImageDataGenerator class, the method of flowing the data from the directory uses a DirectoryIterator object to iterate the data over the directory. We have to extend a custom object from the original DirectorIterator object. For the original one, <a href="https://github.com/tensorflow/tensorflow/blob/r1.8/tensorflow/python/keras/_impl/keras/preprocessing/image.py">GO</a>.</p><pre>class DirectoryIteratorWithBoundingBoxes(DirectoryIterator):<br>    def __init__(self, directory, <strong>image_data_generator</strong>, <strong>bounding_boxes: dict = None</strong>, target_size=(256, 256),<br>                 color_mode: str = &#39;rgb&#39;, classes=None, class_mode: str = &#39;categorical&#39;, batch_size: int = 32,<br>                 shuffle: bool = True, seed=None, data_format=None, save_to_dir=None,<br>                 save_prefix: str = &#39;&#39;, save_format: str = &#39;jpeg&#39;, follow_links: bool = False):<br>        super().__init__(directory, image_data_generator, target_size, color_mode, classes, class_mode, batch_size,<br>                         shuffle, seed, data_format, save_to_dir, save_prefix, save_format, follow_links)<br>        <strong>self.bounding_boxes = bounding_boxes</strong><br><br>    def next(self):<br>        <em>&quot;&quot;&quot;<br>        # Returns<br>            The next batch.<br>        &quot;&quot;&quot;<br>        </em>with self.lock:<br>            <strong>index_array = next(self.index_generator)</strong><br>        # The transformation of images is not under thread lock<br>        # so it can be done in parallel<br>        batch_x = np.zeros((len(index_array),) + self.image_shape, dtype=K.floatx())<br>        <strong>locations = np.zeros((len(batch_x),) + (4,), dtype=K.floatx())</strong><br><br>        grayscale = self.color_mode == &#39;grayscale&#39;<br>        # build batch of image data<br>        for i, j in enumerate(index_array):<br>            fname = self.filenames[j]<br>            img = image.load_img(os.path.join(self.directory, fname),<br>                                 grayscale=grayscale,<br>                                 target_size=self.target_size)<br>            x = image.img_to_array(img, data_format=self.data_format)<br>            x = self.image_data_generator.random_transform(x)<br>            x = self.image_data_generator.standardize(x)<br>            batch_x[i] = x<br><br>            <strong>if self.bounding_boxes is not None:<br>                bounding_box = self.bounding_boxes[fname]<br>                locations[i] = np.asarray(<br>                    [bounding_box[&#39;x1&#39;], bounding_box[&#39;y1&#39;], bounding_box[&#39;x2&#39;], bounding_box[&#39;y2&#39;]],<br>                    dtype=K.floatx())</strong><br>        # optionally save augmented images to disk for debugging purposes<br>        # build batch of labels<br>        if self.class_mode == &#39;sparse&#39;:<br>            batch_y = self.classes[index_array]<br>        elif self.class_mode == &#39;binary&#39;:<br>            batch_y = self.classes[index_array].astype(K.floatx())<br>        elif self.class_mode == &#39;categorical&#39;:<br>            <strong>batch_y = np.zeros((len(batch_x), 46), dtype=K.floatx())</strong><br>            for i, label in enumerate(self.classes[index_array]):<br>                batch_y[i, label] = 1.<br>        else:<br>            return batch_x<br><br>        <strong>if self.bounding_boxes is not None:<br>            return batch_x, [batch_y, locations]<br>        else:<br>            return batch_x, batch_y</strong></pre><p>Bold parts of the code above have been added to DirectoryIterator object to reach category labels and bounding box information at the same time.</p><p>Wuhuuuu!!</p><p>It is mentioned that the size of the images in the dataset are not same, so we need to set a target size for the images in the iterator objects.</p><pre>dict_train, dict_val, dict_test = get_dict_bboxes()</pre><pre>train_iterator = DirectoryIteratorWithBoundingBoxes(&quot;./data/img/train&quot;, train_datagen, bounding_boxes=dict_train, target_size=(200, 200))</pre><pre>test_iterator = DirectoryIteratorWithBoundingBoxes(&quot;./data/img/val&quot;, test_datagen, bounding_boxes=dict_val,target_size=(200, 200))</pre><p>It is the time to add some helpful features to our model. First, we will define a learning rate reducer in order to get rid of the plateaus in the loss function. Also, we will record what our model has done during the training process. Next, we will make sure that the training will be stopped if there is no change in the value of the loss function on the validation set for a certain epoch. Finally, we will save our trained model in each epoch that has better result than previous one.</p><pre>lr_reducer = ReduceLROnPlateau(monitor=&#39;val_loss&#39;,<br>                               patience=12,<br>                               factor=0.5,<br>                               verbose=1)<br>tensorboard = TensorBoard(log_dir=&#39;./logs&#39;)<br>early_stopper = EarlyStopping(monitor=&#39;val_loss&#39;,<br>                              patience=30,<br>                              verbose=1)<br>checkpoint = ModelCheckpoint(&#39;./models/model.h5&#39;)</pre><p>Edit: Thank you to Killian, we have to create a custom generator object which yields the batches of images to the model.</p><pre>def custom_generator(iterator):<br>    while True:<br>        batch_x, batch_y = iterator.next()<br>        yield (batch_x, batch_y)</pre><p>It has been long journey, but we are very close to the end. Keep the faith!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FbrHaCdJqCXijm%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FbrHaCdJqCXijm%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FbrHaCdJqCXijm%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="315" frameborder="0" scrolling="no"><a href="https://medium.com/media/31768bb13350767d628089d9c9d820b3/href">https://medium.com/media/31768bb13350767d628089d9c9d820b3/href</a></iframe><p>We can start training our model.<strong> GO GO GO!!!</strong></p><pre>final_model.fit_generator(custom_generator(train_iterator),<br>                          steps_per_epoch=2000,<br>                          epochs=200, validation_data=custom_generator(test_iterator),<br>                          validation_steps=200,<br>                          verbose=2,<br>                          shuffle=True,<br>                          callbacks=[lr_reducer, checkpoint, early_stopper, tensorboard],<br>                          workers=12)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IFyIqum68gDkLRv9rWHLGw.png" /><figcaption>Head epochs of training</figcaption></figure><p>Waiting…</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FPWfHC8ogZpWcE%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FPWfHC8ogZpWcE%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FPWfHC8ogZpWcE%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="328" frameborder="0" scrolling="no"><a href="https://medium.com/media/587c12d53773099e36e01304bc3747b1/href">https://medium.com/media/587c12d53773099e36e01304bc3747b1/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Dd8o6612qVgtfKxq_mEzBg.png" /><figcaption>20. epoch</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_vyaA98bN0iHLzHsHdE3pg.png" /><figcaption>Just before early stopping</figcaption></figure><p>Well, after early stopping at between 140 and 145th epochs, we can measure the performance of our model on the test set.</p><p>Hold the breath! AND…</p><pre>test_datagen = ImageDataGenerator()<br><br>test_iterator = DirectoryIteratorWithBoundingBoxes(&quot;./data/img/test&quot;, test_datagen, bounding_boxes=dict_test, target_size=(200, 200))</pre><pre>scores = final_model.evaluate_generator(custom_generator(test_iterator), steps=2000)<br><br>print(&#39;Multi target loss: &#39; + str(scores[0]))<br>print(&#39;Image loss: &#39; + str(scores[1]))<br>print(&#39;Bounding boxes loss: &#39; + str(scores[2]))<br>print(&#39;Image accuracy: &#39; + str(scores[3]))<br>print(&#39;Top-5 image accuracy: &#39; + str(scores[4]))<br>print(&#39;Bounding boxes error: &#39; + str(scores[5]))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/679/1*ZdV0My0PxiZcSm3vXPJN6g.png" /><figcaption>Results</figcaption></figure><p>~85% accuracy on top-5 predictions. WOW!</p><p>~&lt;0.05 error on bounding box regression. WOW!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FEktbegF3J8QIo%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FEktbegF3J8QIo%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FEktbegF3J8QIo%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="292" frameborder="0" scrolling="no"><a href="https://medium.com/media/8adf821adca6e936abc06e9ca36119b3/href">https://medium.com/media/8adf821adca6e936abc06e9ca36119b3/href</a></iframe><p>Of course, the results could be improved by increasing the number of augmentation methods and hyperparameter optimization in a certain range, but we are still very close to the results in the paper. It is -definitely- the time to celebrate.</p><p>Well, the fourth episode of “Deep Learning Lab” series, DeepFashion ends here. Thank you for taking the time with me. For comments and suggestions, please <a href="mailto:furkan.kinli@ozu.edu.tr">e-mail</a> me. You can also contact me via <a href="https://www.linkedin.com/in/furkan-kınlı-4b5648116/">LinkedIn</a>. Thank you.</p><p>fk.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2df9e15a63e1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[[Deep Learning Lab] Episode-3: fer2013]]></title>
            <link>https://medium.com/@birdortyedi_23820/deep-learning-lab-episode-3-fer2013-c38f2e052280?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/c38f2e052280</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[neural-networks]]></category>
            <category><![CDATA[fer2013]]></category>
            <category><![CDATA[face-recognition]]></category>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Fri, 06 Apr 2018 09:18:04 GMT</pubDate>
            <atom:updated>2019-03-15T17:37:01.018Z</atom:updated>
            <content:encoded><![CDATA[<p>Let the “Deep Learning Lab” begin!</p><p>This is the third episode of “Deep Learning Lab” story series which contains my individual deep learning works with different cases.</p><ul><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-1-fashion-mnist-c7af60029836">Episode-1: Fashion-MNIST</a></li><li><a href="https://medium.com/deep-learning-turkey/deep-learning-lab-episode-2-cifar-10-631aea84f11e">Episode-2: CIFAR-10</a></li></ul><p>I would like to work on fer2013 dataset, which was published on International Conference on Machine Learning (ICML) 5 years ago, to recognize the facial expression in the third episode.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/753/1*slyZ64ftG12VU4VTEmSfBQ.png" /><figcaption>Example images from fer2013 dataset</figcaption></figure><p>I eidetically hear you ask what this fer2013 is. fer2013 is an open-source dataset which is first, created for an ongoing project by Pierre-Luc Carrier and Aaron Courville, then shared publicly for a Kaggle competition, shortly before ICML 2013. This dataset consists of 35.887 grayscale, 48x48 sized face images with various emotions -7 emotions, all labeled-.</p><p>Emotion labels in the dataset:<br><strong>0:</strong> -4593 images- <em>Angry</em><br><strong>1:</strong> -547 images- <em>Disgust</em><br><strong>2:</strong> -5121 images- <em>Fear</em><br><strong>3:</strong> -8989 images- <em>Happy</em><br><strong>4:</strong> -6077 images- <em>Sad</em><br><strong>5:</strong> -4002 images- <em>Surprise</em><br><strong>6:</strong> -6198 images- <em>Neutral</em></p><p>During the competition, 28.709 images and 3.589 images were shared with the participants as training and public test sets respectively and the remaining 3.589 images were kept as private test set to find the winner of the comptetition. The dataset was set to accessible to everyone after completing the competition.</p><p>Let me reference to the real heroes:</p><blockquote>Challenges in Representation Learning: A report on three machine learning contests, Ian Goodfellow et al., 2013</blockquote><blockquote><a href="https://arxiv.org/pdf/1307.0414.pdf">Universitè de Montrèal, Technical Report</a></blockquote><p><strong>LET’S GET BACK TO 2013…</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FPLtcMkKa1mQDu%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FPLtcMkKa1mQDu%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FPLtcMkKa1mQDu%2Fgiphy-downsized-large.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/f2824681302202931fc3ebb444804a13/href">https://medium.com/media/f2824681302202931fc3ebb444804a13/href</a></iframe><p><strong>LET’S GOOOOO!</strong></p><p>In the demo part of this story, I used JetBrains PyCharm and OpenCV to capture live frames from web camera and to detect the faces and to recognize the emotions on the faces.</p><p>First and foremost: Importing the libraries</p><pre>import sys, os<br>import pandas as pd<br>import numpy as np<br>import cv2<br>from sklearn.model_selection import train_test_split<br>from keras.models import Sequential<br>from keras.layers import Dense, Dropout, Activation, Flatten<br>from keras.layers import Conv2D, MaxPooling2D, BatchNormalization<br>from keras.losses import categorical_crossentropy<br>from keras.optimizers import Adam<br>from keras.regularizers import l2<br>from keras.callbacks import ReduceLROnPlateau, TensorBoard, EarlyStopping, ModelCheckpoint<br>from keras.models import load_model</pre><p>Once you have created a new folder, which is called “Emotion Recognition” in your Google Drive, you need to upload “<a href="https://www.kaggle.com/c/challenges-in-representation-learning-facial-expression-recognition-challenge/data">fer2013.csv</a>” Excel file to this folder. After then, we will define file paths through the virtual machine with the following code snippet.</p><pre>BASEPATH = &#39;drive/Emotion Recognition&#39;<br>sys.path.insert(0, BASEPATH)<br>os.chdir(BASEPATH)<br>MODELPATH = &#39;./models/model.h5&#39;</pre><p>Initializing the parameters.</p><p>We will feed the convolutional neural network with the images as batch, which contains 64 images for each, in 100 epochs and eventually, the network model will output the possibilities of 7 different emotions (num_classes) can belong to the faces on the images sized with 48x48.</p><pre>num_features = 64<br>num_labels = 7<br>batch_size = 64<br>epochs = 100<br>width, height = 48, 48</pre><p>Let’s read our data with the help of “<a href="https://pandas.pydata.org">pandas</a>” from the Excel file we just uploaded to Google Drive.</p><pre>data = pd.read_csv(&#39;./fer2013.csv&#39;)</pre><p>Let’s see what it looks like.</p><pre>data.tail()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/607/1*jScRzdOaQpbSl9QTS4BU6w.jpeg" /><figcaption>The last 5 rows of fer2013 dataset</figcaption></figure><p>As you realized at first glance, the images in the Excel file are stored with the corresponding pixel values on each row and preprocessing on the data is required -a little bit-. (<a href="https://github.com/oarriaga/face_classification">Source for preprocessing</a>)</p><ol><li>Converting the relevant column element into a list for each row</li><li>Splitting the string by space character as a list</li><li>Numpy ❤</li><li>Normalizing the image</li><li>Resizing the image</li><li>Expanding the dimension of channel for each image</li><li>Converting the labels to catergorical matrix</li></ol><pre>pixels = data[&#39;pixels&#39;].tolist() # 1<br><br>faces = []<br>for pixel_sequence in pixels:<br>    face = [int(pixel) for pixel in pixel_sequence.split(&#39; &#39;)] # 2<br>    face = np.asarray(face).reshape(width, height) # 3<br>    <br>    # There is an issue for normalizing images. Just comment out 4 and 5 lines until when I found the solution.</pre><pre>    # face = face / 255.0 # 4<br>    # face = cv2.resize(face.astype(&#39;uint8&#39;), (width, height)) # 5<br>    faces.append(face.astype(&#39;float32&#39;))<br><br>faces = np.asarray(faces)<br>faces = np.expand_dims(faces, -1) # 6<br><br>emotions = pd.get_dummies(data[&#39;emotion&#39;]).as_matrix() # 7</pre><p>We are now ready to split our model into training, validation and test sets -well, I am sure that-.</p><pre>X_train, X_test, y_train, y_test = train_test_split(faces, emotions, test_size=0.1, random_state=42)<br>X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.1, random_state=41)</pre><p>What about the architecture of the model will be?</p><p>[2 x CONV (3x3)] — MAXP (2x2) — DROPOUT (0.5) <br>[2 x CONV (3x3)] — MAXP (2x2) — DROPOUT (0.5) <br>[2 x CONV (3x3)] — MAXP (2x2) — DROPOUT (0.5) <br>[2 x CONV (3x3)] — MAXP (2x2) — DROPOUT (0.5) <br>Dense (512) — DROPOUT (0.5)<br>Dense (256) — DROPOUT (0.5) <br>Dense (128) — DROPOUT (0.5)</p><ul><li>In the first convolutional layer, L2 regularization (0.01) has been added.</li><li>In all convolutional layers except the first one, batch normalization layer has been added.</li><li>MAXP (2x2) and DROPOUT (0.5) layers have been added to each convolutional layers block.</li><li>“RELU” has been picked as activation function for all convolutional layers.</li></ul><pre><strong>model</strong> = Sequential()<br><br><strong>model</strong>.add(Conv2D(num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, input_shape=(width, height, 1), data_format=&#39;channels_last&#39;, kernel_regularizer=l2(0.01)))<br><strong>model</strong>.add(Conv2D(num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, padding=&#39;same&#39;))<br><strong>model</strong>.add(BatchNormalization())<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))<br><strong>model</strong>.add(Dropout(0.5))<br><br><strong>model</strong>.add(Conv2D(2*num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, padding=&#39;same&#39;))<br><strong>model</strong>.add(BatchNormalization())<br><strong>model</strong>.add(Conv2D(2*num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, padding=&#39;same&#39;))<br><strong>model</strong>.add(BatchNormalization())<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))<br><strong>model</strong>.add(Dropout(0.5))<br><br><strong>model</strong>.add(Conv2D(2*2*num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, padding=&#39;same&#39;))<br><strong>model</strong>.add(BatchNormalization())<br><strong>model</strong>.add(Conv2D(2*2*num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, padding=&#39;same&#39;))<br><strong>model</strong>.add(BatchNormalization())<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))<br><strong>model</strong>.add(Dropout(0.5))<br><br><strong>model</strong>.add(Conv2D(2*2*2*num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, padding=&#39;same&#39;))<br><strong>model</strong>.add(BatchNormalization())<br><strong>model</strong>.add(Conv2D(2*2*2*num_features, kernel_size=(3, 3), activation=&#39;relu&#39;, padding=&#39;same&#39;))<br><strong>model</strong>.add(BatchNormalization())<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))<br><strong>model</strong>.add(Dropout(0.5))<br><br><strong>model</strong>.add(Flatten())<br><br><strong>model</strong>.add(Dense(2*2*2*num_features, activation=&#39;relu&#39;))<br><strong>model</strong>.add(Dropout(0.4))<br><strong>model</strong>.add(Dense(2*2*num_features, activation=&#39;relu&#39;))<br><strong>model</strong>.add(Dropout(0.4))<br><strong>model</strong>.add(Dense(2*num_features, activation=&#39;relu&#39;))<br><strong>model</strong>.add(Dropout(0.5))<br><br><strong>model</strong>.add(Dense(num_labels, activation=&#39;softmax&#39;))</pre><p>Let’s see the total trainable / non-trainable parameters.</p><pre>model.summary()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/566/1*M1JBTdIB6yTpbuUe0v9L5Q.jpeg" /><figcaption>The last part of model summary</figcaption></figure><p>We are now ready to compile our model. The categorical crossentropy function has been picked out as a loss function because we have more than 2 labels and already prepared the labels in the categorical matrix structure -I confess, again, copied it from the previous episodes-.</p><pre>model.compile(loss=categorical_crossentropy,<br>              optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-7),<br>              metrics=[&#39;accuracy&#39;])</pre><p>Let’s add some more features to our model.</p><p>Firstly, we help the loss function to get rid of the “plateaus” by reducing the learning rate parameter of the optimization function with a certain value (factor) if there is no improvement on the value of the loss function for the validation set after a certain epoch (patience).</p><pre>lr_reducer = ReduceLROnPlateau(monitor=&#39;val_loss&#39;, factor=0.9, patience=3, verbose=1)</pre><p>We record everything done during the training into the “logs” folder as log to be able to better interpret the results of our model and to visually analyze the changes in the loss function and the accuracy during the training.</p><p>For more information on TensorBoard: <a href="https://www.tensorflow.org/programmers_guide/summaries_and_tensorboard">GO</a></p><pre>tensorboard = TensorBoard(log_dir=&#39;./logs&#39;)</pre><p>Even if we could prevent that the loss function goes to the plateaus, the value of the loss function of validation set could get stuck in a certain range while the training set’s does not (in other words, while the model continues to learn something). As long as we continue to train the model after this point, the only thing the model could do is to memorize (over-fit) the training data -I could say there is no chance of getting rid of the local minima for the loss function without a miracle-. This is something that we will not want at all.</p><p>We stop the training of the model if there is no change in the value of the loss function on the validation set for a certain epoch (patience).</p><pre>early_stopper = EarlyStopping(monitor=&#39;val_loss&#39;, min_delta=0, patience=8, verbose=1, mode=&#39;auto&#39;)</pre><p>Finally, we save our model during training as long as it gets a better result than the previous epoch. Thus, we will have the best possible model at the end of the training.</p><pre>checkpointer = ModelCheckpoint(MODELPATH, monitor=&#39;val_loss&#39;, verbose=1, save_best_only=True)</pre><p>We can start training our model.<strong> GO GO GO!!!</strong></p><pre>model.fit(np.array(X_train), np.array(y_train),<br>          batch_size=batch_size,<br>          epochs=epochs,<br>          verbose=1,<br>          validation_data=(np.array(X_test), np.array(y_test)),<br>          shuffle=True,<br>          callbacks=[lr_reducer, tensorboard, early_stopper, checkpointer])</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r_ShG25yqDRLji1IvIXfPQ.jpeg" /><figcaption>Head epochs of training</figcaption></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgifs.com%2Fiembed%2FKOG3Jz&amp;display_name=http%3A%2F%2Fgifs.com&amp;url=https%3A%2F%2Fgifs.com%2Fgif%2Fspongebob-a-few-moments-later-hd-3-second-video-KOG3Jz&amp;image=https%3A%2F%2Fj.gifs.com%2FKOG3Jz%40small.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=gifs" width="480" height="270" frameborder="0" scrolling="no"><a href="https://medium.com/media/dae1fad8704a762df1f1fa38762bb4f8/href">https://medium.com/media/dae1fad8704a762df1f1fa38762bb4f8/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HKaAqpc4LqesrU6i3CVKUw.jpeg" /><figcaption>Tail epochs of training</figcaption></figure><p>Before measuring the performance of our model on the test set, let’s see the performances of winners’ models in the relevant Kaggle competition in 2013.</p><p>RBM (Yichuan Tang) — <strong>71.162%</strong><br>UNSUPERVISED (Yingbo Zhou &amp; Chetan Ramaiah) — <strong>69.267%</strong><br>MAXIM MILAKOV (Maxim Milakov) — <strong>68.821%</strong><br>RADU+MARIUS+CRISTI (Radu Ionescu &amp; Marius Popescu &amp; Cristian Grozea) — <strong>67.484%</strong></p><p>We , again, all hold our breath, AND…</p><pre>scores = model.evaluate(np.array(X_test), np.array(y_test), batch_size=batch_size)<br>print(&quot;Loss: &quot; + str(scores[0]))<br>print(&quot;Accuracy: &quot; + str(scores[1]))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/224/1*FLPsj6195ua96W_6XMxxug.jpeg" /><figcaption>Loss &amp; Accuracy</figcaption></figure><p>We are very close to the performances of the winners in the competition, but we cannot pass.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/894/1*FlUF0D3ZKUalkFgsSlkqOA.png" /></figure><p>At this point, the most significant problem that I could not solve is that the model starts to memorize the images after a certain number of epochs during the training. I have tried different combinations of optimization function types, different number of epochs and batch sizes, different learning rate values and deeper / shallow / less dense model architectures, but the result has never been improved.</p><p>If so, I would be very pleased to hear your ideas about the solution of this problem.</p><p>The demo of predicting the facial expression of detected faces by <a href="https://docs.opencv.org/3.4.1/d7/d8b/tutorial_py_face_detection.html">Haar-Cascade face detection algorithm</a> by using our trained model:</p><pre>emotion_dict = {0: &quot;Angry&quot;, 1: &quot;Disgust&quot;, 2: &quot;Fear&quot;, 3: &quot;Happy&quot;, 4: &quot;Sad&quot;, 5: &quot;Surprise&quot;, 6: &quot;Neutral&quot;}<br><br><strong>model</strong> = load_model(MODELPATH)<br><br>cap = cv2.VideoCapture(0)<br><br><strong>while</strong> True:<br>    ret, frame = cap.read()<br><br>    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)<br><br>    face_cascade = cv2.CascadeClassifier(&#39;haarcascade_frontalface_default.xml&#39;)<br>    faces = face_cascade.detectMultiScale(gray, 1.3, 5)<br><br>    for (x, y, w, h) <strong>in</strong> faces:<br>        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 1)<br>        roi_gray = gray[y:y + h, x:x + w]<br>        cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)<br>        cv2.normalize(cropped_img, cropped_img, alpha=0, beta=1, norm_type=cv2.NORM_L2, dtype=cv2.CV_32F)<br>        prediction = <strong>model</strong>.predict(cropped_img)<br>        cv2.putText(frame, emotion_dict[int(np.argmax(prediction))], (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 1, cv2.LINE_AA)<br><br>    cv2.imshow(&#39;frame&#39;, frame)<br>    <strong>if</strong> cv2.waitKey(1) &amp; 0xFF == ord(&#39;q&#39;):<br>        <strong>break</strong><br><br>cap.release()<br>cv2.destroyAllWindows()</pre><p>If you try the demo, of course, you may notice that the model does not work very well in some cases. However, if I ask you to say an error rate for this model after trying the demo, you will definitely -and maybe interestingly- say a much smaller error rate than 35% (our model’s).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/801/1*Ir6NT8r4AeC8WhWCCVn8bQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/802/1*ooC5Qft-Qwb2qOEHEtL1pg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*xkqXkFC5AnjbTeZsLFoAWg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/803/1*wSMcJ5ZxQC9AlkGz-1pUQA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/801/1*unwtVtNDVnxSGe4IcLwspQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*HH23yEs5cTKTIsdBjJh36g.png" /><figcaption>Examples of me while trying the demo</figcaption></figure><p><strong>P.S:</strong> I could not act like I disgust or… I might not want to put my disgusted face here. -Kappa-</p><p>Well, the third episode of “Deep Learning Lab” series, fer2013 ends here. Thank you for taking the time with me. For comments and suggestions, please <a href="mailto:furkan.kinli@ozu.edu.tr">e-mail</a> me. You can also contact me via <a href="https://www.linkedin.com/in/furkan-kınlı-4b5648116/">LinkedIn</a>. Thank you.</p><p>fk.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c38f2e052280" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[[Derin Öğrenme Lab] Bölüm-1: Fashion-MNIST]]></title>
            <link>https://medium.com/@birdortyedi_23820/https-medium-com-deep-learning-turkey-derin-ogrenme-lab-bolum-1-fashion-mnist-de4629caa9de?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/de4629caa9de</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[google-colaboratory]]></category>
            <category><![CDATA[fashion-mnist]]></category>
            <category><![CDATA[keras]]></category>
            <category><![CDATA[derin-ogrenme]]></category>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Mon, 05 Mar 2018 06:01:01 GMT</pubDate>
            <atom:updated>2019-03-15T17:36:18.100Z</atom:updated>
            <content:encoded><![CDATA[<p>Derin öğrenme çalışmalarımı paylaşacağım “Derin Öğrenme Lab” serisinin ilk bölümüne başlıyoruz.</p><p>İlk bölüm için çalışmak istediğim veri seti -burada şaşırmıyoruz- MNIST veri seti. Fakat ilk olarak aklınıza geldiği üzere rakamlardan oluşan MNIST değil, kıyafetlerden oluşan MNIST. Yani Fashion-MNIST -burada şaşırıyoruz-.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/638/1*PtQ2I-3RIFiCypor4u_Nbg.jpeg" /><figcaption>Fashion-MNIST</figcaption></figure><p>Çoğunuzun yakından bildiği üzere, orijinal MNIST veri seti, rakamlardan oluşan toplamda 70.000 tane el yazısı rakamdan oluşuyor. Bu setin 60.000 tanesi modeli eğitmek için kullanılırken, 10.000 tanesi ise eğitilen modelin performansını test edebilmek için ayrılmış durumda. Veri seti içerisinden örnekleri aşağıdaki resim ile görebiliriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/1*XsDhBJKWDY4q9_zXT9c8ag.png" /></figure><p>Bildiğimiz el yazısı rakamlardan oluşan MNIST’e alternatif olarak, Zalando Araştırma Ekibi tarafından geliştirilen ve kıyafetlerden oluşan bir veri seti Fashion-MNIST. Atasıyla aynı fiziksel özelliklere sahip, 60.000 resim modeli eğitmek için, 10.000 resim ise eğitilen modelin performansını ölçmek için kullanılıyor. Bu veri setini seçmemin en önemli sebebi şudur ki; Google’da yapılan derin öğrenme ile ilgili aramaların çok büyük çoğunluğu sizi MNIST ile tanıştırabilir, fakat muhtemelen Fashion-MNIST ile ilk defa karşılaşıyorsunuz -yanılıyor muyum?-.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/203/1*_Lk9RADVh7oHmrdR0R-HVQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/251/1*p2jvmf8sLET5V70nzZsAYg.png" /><figcaption>Fashion-MNIST Örnek Resimler</figcaption></figure><p>Referansımızı da şuraya bırakalım:</p><blockquote>Fashion-MNIST: a Novel Image Dataset for Benchmarking Machine Learning Algorithms. Han Xiao, Kashif Rasul, Roland Vollgraf.</blockquote><blockquote><a href="https://arxiv.org/abs/1708.07747">https://arxiv.org/abs/1708.07747</a></blockquote><p>Bu ekip, makine öğrenmesi ve derin öğrenme ile ilgilenen tüm araştırmacılar için neden böyle bir veri seti yaratma ihtiyacı hissettiklerini ise 3 madde ile özetliyorlar:</p><ol><li>MNIST, günümüz algoritmaları için öğrenmesi çok kolay. Çok da derin sayılmayabilecek 2 katmanlı evrişimli(convolutional) sinir ağları ile 99.7% gibi bir başarım oranı mevcut. Klasik makine öğrenmesi algoritmaları için ise bu rakam 97%.</li><li>MNIST çok kullanıldı. Makine öğrenmesi ya da derin öğrenme ile ilgilenmeye başlayan herkes ilk etapta bu veri setini kullandı. Bir nevi, kutsal veri seti oldu. Geçtiğimiz günlerde, Ian Goodfellow (kendisi Google Brain ekibinde önemli bir araştırmacıdır) yeni başlayan kişileri MNIST veri setinden uzak durmaya davet etmişti.</li><li>MNIST günümüzdeki bilgisayarla görü araştırmalarında aşılması gereken problemleri yansıtmaktan çok uzak. <br><em>(Han Xiao et al.)</em></li></ol><p>Fashion-MNIST konusunda yeterince ikna edici olabildiysek, kodlamaya başlayalım.</p><p><strong>LET’S GOOOOO!</strong></p><p>Araştırmalarımda Tensorflow ve Keras kullanıyorum. “Derin Öğrenme Lab” serisinde ise, konu hakkında minimum bilgiye sahip birisine bile kodun nasıl çalıştığını anlayabilme imkanı sunan Keras’ı tercih ettim, edeceğim -niye yalan söyleyeyim, aslında biraz Python bilmek, biraz da literatürü takip etmek de gerek-.</p><p>İlgili kütüphaneleri programımıza tanıtalım.</p><pre>from __future__ import print_function<br>import keras<br>from keras.datasets import fashion_mnist<br>from keras.models import Sequential<br>from keras.layers import Dense, Dropout, Activation, Flatten<br>from keras.layers import Conv2D, MaxPooling2D<br>from keras.utils import print_summary<br>from keras.optimizers import Adam<br>from keras.regularizers import l2<br>import os</pre><p>Parametrelerimizi tanımlayalım.</p><pre>batch_size = 32 # İsterseniz 64 ya da 128 ile de deneyebilirsiniz<br>num_classes = 10<br>epochs = 100 # 93. epoch&#39;tan sonra kayıp fonksiyonu değeri sabit kalmaya başlıyor<br># Modelinizi kaydetmek için:<br>save_dir = os.path.join(os.getcwd(), &#39;saved_models&#39;)<br>model_name = &#39;keras_fashion_mnist_trained_model.h5&#39;</pre><p>Veri setimizi Keras sayesinde çok kolay bir şekilde elde ediyoruz.</p><pre>(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()</pre><p>Veri setimizdeki resimler siyah-beyaz(grayscale) olduğu için veriyi yeniden şekillendirmemiz gerekiyor.</p><pre>x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[2], 1)<br>x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1)<br>input_shape = (28, 28, 1)</pre><p>Veri setimizdeki etiketleri de 1 boyutlu numpy array yapısından kategorik matriks yapısına çevirmemiz gerekiyor.</p><pre>y_train = keras.utils.to_categorical(y_train, num_classes)<br>y_test = keras.utils.to_categorical(y_test, num_classes)</pre><p>Bu kadar “preprocessing” işlemi yeter. Yetmeli :)<br>Artık modelimizi oluşturalım.</p><pre><strong>model</strong> = Sequential()<br><strong>model</strong>.add(Conv2D(32, (3, 3), padding=&#39;same&#39;, kernel_regularizer=l2(0.01), input_shape=input_shape))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(Conv2D(32, (5, 5), kernel_regularizer=l2(0.01)))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2)))<br><strong>model</strong>.add(Dropout(0.25))<br><br><strong>model</strong>.add(Conv2D(64, (3, 3), padding=&#39;same&#39;, kernel_regularizer=l2(0.01)))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(Conv2D(64, (5, 5), kernel_regularizer=l2(0.01)))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2)))<br><strong>model</strong>.add(Dropout(0.25))<br><br><strong>model</strong>.add(Flatten())<br><strong>model</strong>.add(Dense(512))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(Dropout(0.5))<br><strong>model</strong>.add(Dense(num_classes))<br><strong>model</strong>.add(Activation(&#39;softmax&#39;))</pre><p>Bu modelin genel şemasını şu şekilde görebiliriz:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*X9-3RF6kGDP8VqmEDG8EiQ.png" /><figcaption>Modelimiz</figcaption></figure><p>Backprop sırasında ağırlıkları optimize etmek için Adam (Adaptive Moment Estimation) algoritmasını kullandım. Parametrelerini <a href="https://arxiv.org/abs/1412.6980">ilgili makalede</a> belirtildiği üzere default bıraktım.</p><pre>opt = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)</pre><p>O kadar “preprocessing” işlemi yetmemiş… <br>Veri setimizdeki resimleri oluşturan matriksleri normalize etmeyi unuttuk -LUL-.</p><pre>x_train = x_train.astype(&#39;float32&#39;)<br>x_test = x_test.astype(&#39;float32&#39;)<br>x_train /= 255<br>x_test /= 255</pre><p>Artık modelimizi derlemeye hazırız. <br>Kayıp fonksiyonu olarak kategorik çapraz entropi fonksiyonunu seçtik çünkü 2’den fazla etikete sahibiz ve etiketlerimizi kategorik matriks olarak hazırladık.</p><pre>model.compile(loss=&#39;categorical_crossentropy&#39;,<br>              optimizer=opt,<br>              metrics=[&#39;accuracy&#39;])</pre><p>Modelimizi eğitmek için hazırız. GO GO GO!</p><pre>model.fit(x_train, y_train,<br>              batch_size=batch_size,<br>              epochs=epochs,<br>              validation_data=(x_test, y_test),<br>              shuffle=True)</pre><p>Wuhuuu! Biraz hızlı öğreniyoruz, zekiyiz değil mi?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sHmZ7yoUxKh_ooNntExqTA.png" /><figcaption>Epoch 1–5</figcaption></figure><p>Ve eğitimimiz (Google Colaboratory’nin sağlamış olduğu Tesla K80 sayesinde) hızlı bir şekilde tamamlanıyor. Şimdi modelimizin performansını daha önce hiç görmediğimiz test veri seti ile ölçme zamanı.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YO6n571QOQkXDJHEjhJSSA.png" /><figcaption>Epoch 93–100</figcaption></figure><p>Performans ölçümü için şu kod parçacığını çalıştırmamız yeterli.</p><pre>scores = model.evaluate(x_test, y_test, verbose=1)<br>print(&#39;Test loss:&#39;, scores[0])<br>print(&#39;Test accuracy:&#39;, scores[1])</pre><p>VEEEEEE… TA TAAA!!!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/474/1*AxpGRiufuwumN06S2FpHkA.png" /><figcaption>Test seti üzerindeki başarım oranımız</figcaption></figure><p>Modelimiz tahmin ettiği 10.000 test resminin 90.52%’ini doğru tahmin etmiş. Literatür performansları için: <a href="https://github.com/zalandoresearch/fashion-mnist">Tıklıyoruz</a> (Benchmark başlığı altında görebilirsiniz)</p><p>Evet “Derin Öğrenme Lab” serisinin ilk bölümü olan Fashion-MNIST burada bitiyor. Yayında ve yapımda emeği geçen herkese teşekkürler. Yorumlar ve öneriler için <a href="mailto:furkan.kinli@ozu.edu.tr">mail</a> atabilirsiniz. Ayrıca bana ulaşmak için <a href="https://www.linkedin.com/in/furkan-kınlı-4b5648116/">LinkedIn</a> hesabımı kullanabilirsiniz.</p><p>Yazının orijinaline kişisel web sayfamdan ulaşmak için: <a href="https://birdortyedi.github.io/birdortyedi/2018/01/30/derin-%C3%B6%C4%9Frenme-lab-b%C3%B6l%C3%BCm-1">GO!</a></p><p>fk.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=de4629caa9de" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[[Deep Learning Lab] Episode-2: CIFAR-10]]></title>
            <link>https://medium.com/@birdortyedi_23820/deep-learning-lab-episode-2-cifar-10-631aea84f11e?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/631aea84f11e</guid>
            <category><![CDATA[cifar-10]]></category>
            <category><![CDATA[convolutional-network]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[computer-vision]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Sun, 18 Feb 2018 07:01:01 GMT</pubDate>
            <atom:updated>2019-03-15T17:35:22.888Z</atom:updated>
            <content:encoded><![CDATA[<p>Let the “Deep Learning Lab” begin!</p><p>This is the second episode of “Deep Learning Lab” story series which contains my individual deep learning works with different cases.</p><p>I would like to work on CIFAR datasets in the second episode. CIFAR-10 and CIFAR-100 are two different datasets with different number of classes -please take a hint, it’s all about names-. First, it’s the time to start with CIFAR-10, which is -relatively- easier to work and actually, working on CIFAR-100 in such a different case has been already planned for the later part of the series.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/356/1*QN007xhxgDTPBdNT0pnZ2g.png" /><figcaption>CIFAR-10</figcaption></figure><p>Let’s quickly get to know the CIFAR-10 dataset. CIFAR-10 is one of the most well-known image dataset containing 60.000 different images which is created by the first person that should come to your mind in deep learning and his teammates. OFC, I’m talking about Geoffrey Hinton. CIFAR-10 is labeled subsets of the “<a href="http://people.csail.mit.edu/torralba/tinyimages/">80 million tiny images</a>” dataset. (G. Hinton, A. Krizhevsky and V. Nair in Canadian Institute for Advanced Research)</p><p>The size of all images in this dataset is 32x32x3 (RGB). If you don’t have any idea of what are the “3” in the third dimension and “RGB” in the brackets mean, I strongly recommend you to read <a href="http://sun.aei.polsl.pl/~mkawulok/stud/graph/instr.pdf">this article</a>. Moreover, there are 50.000 images for training a model and 10.000 images for evaluating the performance of the model. The classes and randomly selected 10 images of each class could be seen in the picture below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/527/1*RHQnoF0uUH0h0M8qkakd1Q.png" /><figcaption>Classes and randomly selected 10 images of each class</figcaption></figure><p>Let me reference to the real hero:</p><blockquote>Learning Multiple Layers of Features from Tiny Images, Alex Krizhevsky, 2009</blockquote><blockquote><a href="https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf">University of Toronto, Technical Report</a></blockquote><p>I am looking forward to creating an accurate deep learning model on the CIFAR-10 dataset. Let’s start coding!</p><p><strong>LET’S GOOOOO!</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*83CuvBlu2iosnewOQSeiPg.jpeg" /><figcaption>Randomly selected 24 images in CIFAR-10 dataset</figcaption></figure><p>The very first move: Importing the libraries</p><pre>from __future__ import print_function<br>import keras<br>from keras.datasets import cifar10<br>from keras.models import Sequential<br>from keras.layers import Dense, Dropout, Activation, Flatten<br>from keras.layers import Conv2D, MaxPooling2D<br>from keras.optimizers import SGD<br>from keras.utils import print_summary, to_categorical<br>import sys<br>import os</pre><p>We need to assign a file path on Google Drive to save the model that we trained on Google Colaboratory. The first thing to do is to create a new folder named “cifar10” on Google Drive and then, let’s run the following code snippet on Google Colab.</p><pre>sys.path.insert(0, &#39;drive/cifar10&#39;)<br>os.chdir(“drive/cifar10”)</pre><p>Initializing the parameters.</p><p>We will feed the convolutional neural network with the images as batches -each batch contains 64 images- in 100 epochs and eventually, the network model will output the possibilities of 10 different categories (num_classes) can belong to the image.</p><pre>batch_size = 64<br>num_classes = 10<br>epochs = 100<br>model_name = &#39;keras_cifar10_model&#39;<br>save_dir = &#39;/model/&#39; + model_name</pre><p>Thanks to Keras, we can load the dataset easily.</p><pre>(x_train, y_train), (x_test, y_test) = cifar10.load_data()</pre><p>We also need to convert the labels in the dataset into categorical matrix structure from 1-dim numpy array structure.</p><pre>y_train = to_categorical(y_train, num_classes)<br>y_test = to_categorical(y_test, num_classes)</pre><p>Once bitten twice shy, we will not forget it for this time. We need to normalize the images in the dataset.</p><pre>x_train = x_train.astype(&#39;float32&#39;)<br>x_test = x_test.astype(&#39;float32&#39;)<br>x_train /= 255.0<br>x_test /= 255.0</pre><p>We are now absolutely sure that it is enough for preprocessing -for now, LUL-. It is the time to create our model. For this episode in the series, I would prefer to use the most common neural network model architecture in the literature: [CONV] — [MAXP] -..- [CONV] — [MAXP] — [Dense]</p><pre><strong>model</strong> = Sequential()<br><strong>model</strong>.add(Conv2D(32, (3, 3), padding=&#39;same&#39;, input_shape=x_train.shape[1:]))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2)))<br><strong>model</strong>.add(Dropout(0.3))<br><br><strong>model</strong>.add(Conv2D(64, (3, 3), padding=&#39;same&#39;, input_shape=x_train.shape[1:]))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2)))<br><strong>model</strong>.add(Dropout(0.3))<br><br><strong>model</strong>.add(Conv2D(128, (3, 3), padding=&#39;same&#39;, input_shape=x_train.shape[1:]))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2)))<br><strong>model</strong>.add(Dropout(0.4))<br><br><strong>model</strong>.add(Flatten())<br><strong>model</strong>.add(Dense(80))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(Dropout(0.3))<br><strong>model</strong>.add(Dense(num_classes))<br><strong>model</strong>.add(Activation(&#39;softmax&#39;))</pre><p>The summary of this model could be seen below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/517/1*U9HN2K9O_2GZAjX_tQV5yg.png" /><figcaption>Summary of model</figcaption></figure><p>I would prefer the Stochastic Gradient Descent algorithm to optimize the weights on the backpropagation. Set the momentum parameter as 0.9, and just leave the others as default. I, again, strongly recommend you to read an article, <a href="http://leon.bottou.org/publications/pdf/compstat-2010.pdf">this one</a>, in order to get more information about SGD algorithm.</p><pre>opt = SGD(lr=0.01, momentum=0.9, decay=0, nesterov=False)</pre><p>We are now ready to compile our model. The categorical crossentropy function has been picked out as a loss function because we have more than 2 labels and already prepared the labels in the categorical matrix structure -I confess, copied it from the first episode-.</p><pre>model.compile(loss=&#39;categorical_crossentropy&#39;,<br>              optimizer=opt,<br>              metrics=[&#39;accuracy&#39;])</pre><p>We’ve done a lot and we have only one step to begin training our model. At this time, I would like to make a different move. I will split the training dataset (50.000 images) into training (40.000 images) and validation (10.000 images) datasets to measure the validation accuracy of our model in such a better way. Thus, our neural network model will continue the training by evaluating the images that never been seen during the training after each epoch.</p><pre>model.fit(x_train, y_train,<br>          batch_size=batch_size,<br>          epochs=epochs,<br>          validation_split=0.2,<br>          shuffle=True)</pre><p>Well, so far so good. We have started to learn. I think we did, didn’t we?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Tk_75FF8WYzja8oVHIZX9A.png" /><figcaption>Epochs 1–5</figcaption></figure><p>In contrast to the previous episode, training our model took a long time despite using a powerful GPU -thanks to Google Colab-. After about 4 hours of training, it could be seen like below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GATsLbwcOk0XFSqGSkORVQ.png" /><figcaption>Epochs 95–100</figcaption></figure><p>Just before measuring the accuracy of our model with the test dataset, I would like to share with you the achievements obtained using the CIFAR-10 dataset. <a href="http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html">GO!</a></p><p>We all hold our breath, AND…</p><pre>scores = model.evaluate(x_test, y_test, verbose=1)<br>print(&#39;Test loss:&#39;, scores[0])<br>print(&#39;Test accuracy:&#39;, scores[1])</pre><p>The result:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/487/1*wVLkaJTIxZnewwdlYWuC-A.png" /></figure><p>Our -lovely- model classifies 77.37% of 10.000 test images.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FmuHlnG1WU9YfS%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FmuHlnG1WU9YfS%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FmuHlnG1WU9YfS%2F200w.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="489" frameborder="0" scrolling="no"><a href="https://medium.com/media/b52768042f41e827e314f2830888e65c/href">https://medium.com/media/b52768042f41e827e314f2830888e65c/href</a></iframe><p>We -really- need to look at the performances in the literature and I -indeed- don’t believe that we fall even further behind. I’m proud of this figure since our model has just 3 layers with simple neural network architecture and trained only 4 hours.</p><p>So what do you think?</p><p>What should we do to improve the performance of our model?</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FxW5gVURP2l0Uo%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FxW5gVURP2l0Uo%2Fgiphy.gif&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FxW5gVURP2l0Uo%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="243" frameborder="0" scrolling="no"><a href="https://medium.com/media/06676f03abd136255f7f0259d51dc42b/href">https://medium.com/media/06676f03abd136255f7f0259d51dc42b/href</a></iframe><p>The first answer for this question: Train the model for a while.</p><p>I’m not a lazy guy -HUH-.</p><p>Results:</p><p><strong>100 epochs:</strong> Accuracy: <strong>77.37%</strong>, Loss: <strong>0.670</strong><br><strong>150 epochs:</strong> Accuracy: <strong>78.22%</strong>, Loss: <strong>0.646</strong><br><strong>200 epochs:</strong> Accuracy: <strong>77.77%</strong>, Loss: <strong>0.670</strong></p><p>I won’t continue to train this model anymore -of course- since there was no improvement in the loss function values after 170–175th epochs. In other words, our model will start to overfitting. If it is trained more -as is-, the performance of test dataset will begin decreasing, which is the last thing we would like to happen.</p><p>Well, what else can we do?</p><p>Yes, possible, we can still do something to improve the performance of our model.</p><p>For example:</p><ul><li><strong>Data augmentation.</strong> We can efficiently increase the number of images in the dataset with the help of a method in Keras library named “ImageDataGenerator” by augmenting the images with horizontal/vertical flipping, rescaling, rotating and whitening etc. The more data we have for training, the more accurate result we could obtain -here, I do not claim that data augmentation always guarantees better accuracy-.</li><li><strong>Changing optimizer.</strong> Stochastic Gradient Descent algorithm to optimize the weights is <strong><em>probably</em></strong> not the most appropriate algorithm for this dataset. There <strong><em>may</em></strong> be an increase in the performance -attention! I’m not talking about a definite increase”.</li><li><strong>Changing learning rate.</strong> We could decrease the learning rate of the model a bit after 170th epoch. It is possible to change the learning rate during the training by helping of the methods in Keras library named “LearningRateScheduler” and “ReduceLROnPlateau”.</li><li><strong>Changing the architecture. </strong>If the performance of our model still does not satisfy us, we will have to question the architecture of the model that we are building. We need to try to resemble our model to more modern neural networks like ResNet and VGGNet or we need to change the activation functions of the layers in the model. Then, we will have a chance to improve the performance.</li></ul><p>Before summing up, I would like to save our model as a file with extension “.h5”. Thus, I can continue to train my model, I can convert the model into a software which predicts “real-case” pictures that the model has never met before and I can share the model with other deep learning researchers who would like to use this model.</p><pre>model.save(save_dir + &#39;.h5&#39;)</pre><p>Well, the second episode of “Deep Learning Lab” series, CIFAR-10 ends here. Thank you for taking the time with me. For comments and suggestions, please <a href="mailto:furkan.kinli@ozu.edu.tr">e-mail</a> me. You can also contact me via <a href="https://www.linkedin.com/in/furkan-kınlı-4b5648116/">LinkedIn</a>. Thank you.</p><p>fk.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=631aea84f11e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[[Deep Learning Lab] Episode-1: Fashion-MNIST]]></title>
            <link>https://medium.com/@birdortyedi_23820/deep-learning-lab-episode-1-fashion-mnist-c7af60029836?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/c7af60029836</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[fashion]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[mnist]]></category>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Fri, 02 Feb 2018 08:01:07 GMT</pubDate>
            <atom:updated>2019-03-15T17:34:26.064Z</atom:updated>
            <content:encoded><![CDATA[<p>Let the “Deep Learning Lab” begin!</p><p>This is the first episode of “Deep Learning Lab” story series which contains my individual works for deep learning with different cases.</p><p>The dataset for the first episode that I would like to work on is MNIST dataset -not surprisingly-. However, it is not MNIST handwritten digit database as first come to your mind, but MNIST-like fashion product database. Actually, Fashion-MNIST -wow!-.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/638/1*PtQ2I-3RIFiCypor4u_Nbg.jpeg" /><figcaption>Fashion-MNIST</figcaption></figure><p>Fashion-MNIST dataset has been developed by the Zalando Research Team as clothes product database and as an alternative to the original MNIST handwritten digits database. Besides to have the same physical characteristics as the ancestor (the original one), there are 60.000 images for training a model and 10.000 images for evaluating the performance of the model. The most significant reason for picking this dataset is that the vast majority of searches about deep learning on Google may introduce you to the original MNIST, but you are now probably meeting Fashion-MNIST for the first time -don’t you?-.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/251/1*p2jvmf8sLET5V70nzZsAYg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/203/1*_Lk9RADVh7oHmrdR0R-HVQ.png" /><figcaption>Example images of Fashion-MNIST</figcaption></figure><p>Let me reference to the real heroes:</p><blockquote>Fashion-MNIST: a Novel Image Dataset for Benchmarking Machine Learning Algorithms. Han Xiao, Kashif Rasul, Roland Vollgraf.</blockquote><blockquote><a href="https://arxiv.org/abs/1708.07747">https://arxiv.org/abs/1708.07747</a></blockquote><p>Zalando team summarizes why they think that there is a need to create such a dataset for machine learning and deep learning researchers, with these 3 sentences:</p><ol><li>MNIST is too easy. Convolutional nets can achieve 99.7% on MNIST. Classic machine learning algorithms can also achieve 97% easily.</li><li>MNIST is overused. In this April 2017 Twitter thread, Google Brain research scientist and deep learning expert Ian Goodfellow calls for people to move away from MNIST.</li><li>MNIST can not represent modern computer vision tasks.</li></ol><p><em>(Han Xiao et al.)</em></p><p>If I succeeded in convincing you enough for Fashion-MNIST, let’s start coding.</p><p><strong>LET’S GOOOOO!</strong></p><p>I prefer to use Tensorflow and Keras for my works. In the “Deep Learning Lab” series, I would like to choose Keras, which gives you an opportunity to understand how the code works even if you have minimum/no knowledge of the subject -well, not tell a lie; it needs to know a bit about Python, and also to follow the literature-.</p><p>Importing the libraries.</p><pre>from __future__ import print_function<br>import keras<br>from keras.datasets import fashion_mnist<br>from keras.models import Sequential<br>from keras.layers import Dense, Dropout, Activation, Flatten<br>from keras.layers import Conv2D, MaxPooling2D<br>from keras.utils import print_summary<br>from keras.optimizers import Adam<br>from keras.regularizers import l2<br>import os</pre><p>Initializing the parameters.</p><pre>batch_size = 32 # You can try 64 or 128 if you&#39;d like to<br>num_classes = 10<br>epochs = 100 # loss function value will be stabilized after 93rd epoch<br># To save the model:<br>save_dir = os.path.join(os.getcwd(), &#39;saved_models&#39;)<br>model_name = &#39;keras_fashion_mnist_trained_model.h5&#39;</pre><p>Thanks to Keras, we can load the dataset easily.</p><pre>(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()</pre><p>We need to reshape the data since the images in the dataset are grayscaled.</p><pre>x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[2], 1)<br>x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1)<br>input_shape = (28, 28, 1)</pre><p>We also need to convert the labels in the dataset into categorical matrix structure from 1-dim numpy array structure.</p><pre>y_train = keras.utils.to_categorical(y_train, num_classes)<br>y_test = keras.utils.to_categorical(y_test, num_classes)</pre><p>Enough for preprocessing. It should be :).<br>Now let’s build our model.</p><pre><strong>model</strong> = Sequential()<br><strong>model</strong>.add(Conv2D(32, (3, 3), padding=&#39;same&#39;, kernel_regularizer=l2(0.01), input_shape=input_shape))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(Conv2D(32, (5, 5), kernel_regularizer=l2(0.01)))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2)))<br><strong>model</strong>.add(Dropout(0.25))<br><br><strong>model</strong>.add(Conv2D(64, (3, 3), padding=&#39;same&#39;, kernel_regularizer=l2(0.01)))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(Conv2D(64, (5, 5), kernel_regularizer=l2(0.01)))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(MaxPooling2D(pool_size=(2, 2)))<br><strong>model</strong>.add(Dropout(0.25))<br><br><strong>model</strong>.add(Flatten())<br><strong>model</strong>.add(Dense(512))<br><strong>model</strong>.add(Activation(&#39;relu&#39;))<br><strong>model</strong>.add(Dropout(0.5))<br><strong>model</strong>.add(Dense(num_classes))<br><strong>model</strong>.add(Activation(&#39;softmax&#39;))</pre><p>The summary of this model could be seen below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*X9-3RF6kGDP8VqmEDG8EiQ.png" /><figcaption>Our Model</figcaption></figure><p>I used Adam (Adaptive Moment Estimation) algorithm to optimize the weights during the backpropagation. Just left the parameters default as specified in <a href="https://arxiv.org/abs/1412.6980">the relevant article</a>.</p><pre>opt = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)</pre><p>Not enough preprocessing… We forgot to normalize the images in the dataset -LUL-.</p><pre>x_train = x_train.astype(&#39;float32&#39;)<br>x_test = x_test.astype(&#39;float32&#39;)<br>x_train /= 255<br>x_test /= 255</pre><p>We are now ready to compile our model. The categorical crossentropy function has been picked out as a loss function because we have more than 2 labels and already prepared the labels in the categorical matrix structure.</p><pre>model.compile(loss=&#39;categorical_crossentropy&#39;,<br>              optimizer=opt,<br>              metrics=[&#39;accuracy&#39;])</pre><p>We are ready to train our model. GO GO GO!</p><pre>model.fit(x_train, y_train,<br>              batch_size=batch_size,<br>              epochs=epochs,<br>              validation_data=(x_test, y_test),<br>              shuffle=True)</pre><p>Wuhuuu! We learn a bit fast. It is very smart, isn’t it?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sHmZ7yoUxKh_ooNntExqTA.png" /><figcaption>Epoch 1–5</figcaption></figure><p>Our training has been completed in a couple of shakes (Thanks to Tesla K80 and Google Colaboratory). Now it’s time to measure the performance of our model with the test set.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YO6n571QOQkXDJHEjhJSSA.png" /><figcaption>Epoch 93–100</figcaption></figure><p>To evaluate the performance, we only need to run the following code snippet.</p><pre>scores = model.evaluate(x_test, y_test, verbose=1)<br>print(&#39;Test loss:&#39;, scores[0])<br>print(&#39;Test accuracy:&#39;, scores[1])</pre><p>AND… TA TA TAM!!!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/474/1*AxpGRiufuwumN06S2FpHkA.png" /><figcaption>Test Accuracy</figcaption></figure><p>Our model predicted 90.52% of 10.000 test images as correct. For the literature performances: <a href="https://github.com/zalandoresearch/fashion-mnist">GO!</a> (You can see under the Benchmark heading)</p><p>Well, the first episode of “Deep Learning Lab” series, Fashion-MNIST ends here. Thank you for taking the time with me. For comments and suggestions, please <a href="mailto:furkan.kinli@ozu.edu.tr">e-mail</a> me. You can also contact me via <a href="https://www.linkedin.com/in/furkan-kınlı-4b5648116/">LinkedIn</a>. Thank you.</p><p>fk.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c7af60029836" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bir KÖRS Hikayesi: not winner but WINNER]]></title>
            <link>https://medium.com/@birdortyedi_23820/bir-k%C3%B6rs-hikayesi-not-winner-but-winner-60d86a5fc367?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/60d86a5fc367</guid>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Wed, 05 Jul 2017 21:27:45 GMT</pubDate>
            <atom:updated>2017-07-05T21:29:56.999Z</atom:updated>
            <content:encoded><![CDATA[<iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fe2aJuKZCnx0%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3De2aJuKZCnx0&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fe2aJuKZCnx0%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/d522ae720bea111be68628d587103a79/href">https://medium.com/media/d522ae720bea111be68628d587103a79/href</a></iframe><p>Dıt dıt dırıt dıt dı dıt dırıttı dı dıt…</p><p>Sertap Erener’in kazandığı 1.lik ile birlikte ilgimi çeken ve takip etmeye başladığım Eurovision Şarkı Yarışması hakkında bir şeyler karalamak istedim bu sefer. Özellikle son 5 yıldır (Türkiye&#39;nin yarışmadan süresiz çekildiği tarihle denk gelmesi tamamen tesadüf) baya baya Eurovision gurmesi olmaya başladığımı söyleyebilirim.</p><p>Tabi ki her sene ocak-şubat döneminde o senenin şarkılarının piyasa çıkması, defalarca dinlenip tahlil edilmesi, sevilen şarkıların daha fazla dinlenmesi, takılan şarkının hep dinlenmesi gibi süreçler mayısın ikinci haftasına kadar sonsuz döngü misali devam ediyor. Bazen bu durum çevremdeki insanları bezdirecek seviyeye gelse de, yarışma tarihi yaklaştıkça heyecan da artıyor onlarda da.</p><p>Mutlaka her sene bir favori şarkı seçiyorum ama son yıllarda resmen seçtiğim şarkının üzerine lanet getiriyorum. Bir şekilde bu şarkılar kazanamıyor.</p><p>KÖRS’ün Başlangıcı: Yohanna — Is It True?(Sene: 2009 — Derece: 2)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FqqE69feyEOU%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DqqE69feyEOU&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FqqE69feyEOU%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/54f57521b8cd6673eca24a585dbf2271/href">https://medium.com/media/54f57521b8cd6673eca24a585dbf2271/href</a></iframe><p>FAK Lena, GO Manga dedik ama: maNga — We Could Be The Same(Sene: 2010 — Derece: 2)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F524Yy7JWBd4%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D524Yy7JWBd4&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F524Yy7JWBd4%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/dde1a239ae89bcd9d6862cd1e0561213/href">https://medium.com/media/dde1a239ae89bcd9d6862cd1e0561213/href</a></iframe><p>Eurovision’un Zeljko’su: Zeljko Joksimovic — Nje Ljubav Stvar(Sene: 2012 — Derece: 3)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FR9x9VbJzaDQ%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DR9x9VbJzaDQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FR9x9VbJzaDQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/10fe9d968331d2f823941b5e2e8b154b/href">https://medium.com/media/10fe9d968331d2f823941b5e2e8b154b/href</a></iframe><p>KÖRS’ün Yükselişi: Sanna Nielsen — Undo(Sene: 2014 — Derece: 3)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F5PQJI-3LW-8%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D5PQJI-3LW-8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F5PQJI-3LW-8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/eed06149b6eb520e4d82e21b18c56fe6/href">https://medium.com/media/eed06149b6eb520e4d82e21b18c56fe6/href</a></iframe><p>KÖRS çok bozdu, baya bozdu yani öyle böyle değil, inanılmaz bozdu, çok fazla bozdu yani, o kadar bozdu önünü alamadık öyle kötü bozdu yani, bozdu, bozdu, bozdu, bir yerden sonra bozmaz diye bekledik, daha da bozdu, artık bozmasın dedik, iyice bozdu.</p><p>KÖRS’ün Zirvesi, Şarkıların Kralı: Il Volo — Grande Amore (Sene: 2015 — Derece: 3)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F1TOMqZV2jA8%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D1TOMqZV2jA8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F1TOMqZV2jA8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ae1d38e448bdc082bec9c2d18b095dbe/href">https://medium.com/media/ae1d38e448bdc082bec9c2d18b095dbe/href</a></iframe><p>Sessizliğin Sesi Dami Ablamız: Dami Im — Sound of Silence (Sene: 2016 — Derece: 2)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F5ymFX91HwM0%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D5ymFX91HwM0&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F5ymFX91HwM0%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/d0ee8389d4accef5c6f769384cad3de8/href">https://medium.com/media/d0ee8389d4accef5c6f769384cad3de8/href</a></iframe><p>Bu Sefer KÖRS’ü Yıktık Dedik Ama…: Francesco Gabbani — Occidentali’s Karma (Sene: 2017 — Derece: 6)</p><p>(141 Milyon tekil izlenmesi vardı. Kaliteliydi. Bahis oranlarında 4 ay açık ara önde gitti. Bütün ön partilerde, değerlendirmelerde 1. olacağı konuşuluyordu. Sahnede goril oynattı. Olmadı. Thanks to KÖRS)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F-OnRxfhbHB4%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D-OnRxfhbHB4&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F-OnRxfhbHB4%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/699d27eb61aabba01929dbd8da5cedbc/href">https://medium.com/media/699d27eb61aabba01929dbd8da5cedbc/href</a></iframe><p>Bu da böyle bir KÖRS hikayesiydi. Bakalım önümüzdeki sene hangi şarkının başını yakacağım. Bekliyoruz. Road to Lizbon 2018.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=60d86a5fc367" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Başlangıç]]></title>
            <link>https://medium.com/@birdortyedi_23820/ba%C5%9Flang%C4%B1%C3%A7-37c1abc4b4b1?source=rss-da685a287e6a------2</link>
            <guid isPermaLink="false">https://medium.com/p/37c1abc4b4b1</guid>
            <dc:creator><![CDATA[Furkan Kınlı]]></dc:creator>
            <pubDate>Fri, 30 Jun 2017 22:53:10 GMT</pubDate>
            <atom:updated>2017-07-28T16:34:17.805Z</atom:updated>
            <content:encoded><![CDATA[<p>İlginçtir ki, uzun süre boyunca haber sitesi kıvamındaki bloglarda birçok yazı yazmama rağmen, kendim hakkında bir şeyler karalamak için cesaretimi bir süredir toplayamıyordum. Peki ne değişti?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*hpqQuTmBa4n6Nw66dCpJHg.jpeg" /><figcaption>İlgi çekme resmi.</figcaption></figure><p>Öncelikle kendimden bahsetmeliyim. Furkan Kınlı. 24.5 yaşındayım. Özyeğin Üniversitesi’nde Mühendislikte Bilgisayar Bilimleri okuyorum (Vallahi İngilizce sayfasında Computer Science in Engineering yazıyor). Bilgisayarla görü ve makine öğrenmesi alanlarında mümkün olduğunca literatürü takip ederek kendimi geliştirmeye çalışıyorum. Yani kendimi “yazılımcı” olarak nitelendirmek istemiyorum. Değilim çünkü.</p><p>Her üniversite öğrencisi bilir, bir üniversiteden lisans diploması alabilmek için saha tecrübesi edinmek adına staj koşulu/dersi vardır. Benim de mezun olabilmem için 40 saatlik bir iş tecrübesi yaşamam gerekiyor. İlk 4 dönem boyunca konu ile ilgili hiçbir endişem yoktu tabi ki. “Zamanı gelince” yapardım çünkü. Üzülerek belirtiyorum, kendi kafamda şişe kırmışım, bayılmışım haberim yok.</p><p>Zamanı geldi ve tabi büyük bir heyecan ile 0 (yazıyla sıfır) proje, niteliksiz deneyimler ve hobilerimden oluşan bir CV hazırladım. Malum siteyi açtım. Arama çubuğuna Bilgisayar Mühendisi, Yazılım Mühendisi vb. girdilerin ardından başladım “staj” aramaya. En kötü tanıdıklardan bir şeyler ayarlanırdı muhakkak. Koskoca “Bilgisayar Mühendisi” adayıyım işsiz mi kalacağım bulurum elbet şöyle fiyakalı bir staj. Değil mi? LUL.</p><p>Bırakın mülakat davetini, çoğu şirketten geri dönüş bile alamadım. Geri dönüş yapanların da cümleleri tek ağızdan çıkmış gibiydi sanki. “Şirketimize yaptığınız başvuru incelenmiş yapılan değerlendirmeler neticesinde ilgili pozisyon için şu anda sizinle bla bla bla”. Bir anda tanıdıklar da ortadan kaybolunca stajımı yapmam gereken dönemde yapamadım ve daha kötüsü öz güvenim kırıldı. Çevremdeki halalar, dayılar hal hatır sordukça canım sıkılıyor, daha da içime kapanıyordum çünkü cevap veremiyordum. Aslında kendime cevap veremiyordum. Sonuç olarak kendine güveni olmayan, önemsiz ve başarısız hisseden, psikolojisi bozulan ve çevresindeki insanlardan uzaklaşan bir birey olup çıktım. Bu durum okulda NŞA’daki son dönemim olması gereken döneme dek devam etti (Okul uzadı, teşekkürler dif).</p><p>Hikaye bir noktada değişecek elbette. İşte o noktadayız.</p><p>Malum ders yüzünden (diferansiyel denklemlerden bahsediyorum tabi ki) 8. dönemime sarkan bir 3.sınıf dersim ve o dersimin hocası beni, dolayısıyla da her şeyi, değiştirdi. Teknik sunum. Dersin içeriği olarak da İngilizce olarak nasıl verimli sunum yapılır, sunum yaparken nelere dikkat etmeliyiz gibi kazanımlarımız var. Dersi geçebilmek için iki kere sunum yapmamız gerekiyor. Birincisinde hikayeye göre bir konferansta gördüğümüz Sİ İ O ile tanışmaya çalışıyoruz, kendimizi tanıtıyoruz; ikincisinde ise bir girişimciyi oynuyoruz ve projemizi iş adamlarına sunarak fon almaya çalışıyoruz. Bu noktaya kadar her şey normal. Neredeyse her üniversitede olan zorunlu derslerden biri aslında. Burada kilit nokta dersin hocasının yaklaşımı.</p><p>Herhangi bir dersten çok farklı şekilde, bir hayat dersi, bir kişisel gelişim ve uyanış dersi oldu bu benim için. Burak Hocanın bana kazandırdığı öz güven hayata bakış açımı değiştirdi. Kendimi geliştirmem için ilgilenmem gereken odak noktaları bana hatırlattı. İlk dersinden çıkıp kız arkadaşıma dersi anlatırken halimi hala hatırlıyorum. İnanılmaz.</p><p>Kendimi fark etmem, kendimi geliştirmek için çabalamam ve öz güvenimin yeniden kazanılmasıyla başvurular için hazırdım. Daha özenli ve beni anlatan bir CV hazırlamakla işe başladım. Ardından yapmak istediğim şeyi belirledim ve buna paralel olarak belli başlı yerlere başvurularımı yaptım. Bingo! Önce genel yetenek testleri, ardından İngilizce testleri ve video mülakatları…</p><p>İyi gidiyordum. Artık sıra bendeydi. Mülakatlar sırasında sanki sahnede gösteri yapıyor gibi hissediyordum kendimi. Son bireysel mülakatımda, sunum sırasında değerli İK uzmanı, bana “darlayıcı” soru sorma ihtiyacı hissetmedi ve 20 dakika muhabbet ettik. Biliyordum bu sefer olacaktı. Ve oldu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*xP7pUyEliYPqjL_OzVXpUQ.jpeg" /></figure><p>Türk Telekom START Staj Programına kabul edildiğim haberini aldım. Çok istemiştim ve oldu. Kendimce hak ettiğimi düşünüyordum. O an herkes öyle düşünürdü sanırım. Bu noktada Burak Hocama bana kattığı değeri ve kendimin farkına varmamı sağladığı için çok*sonsuz teşekkür ediyorum.</p><p>Ve staj programım 2 gün sonra başlıyor. <br>Good game. Well played. Well deserved.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=37c1abc4b4b1" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>