• টেনসরফ্লো মডেলটিকে প্রশিক্ষণের জন্য বাস্তব জীবনের ডেটা সেট প্রস্তুত করুন।

    টেনসরফ্লো মডেলটিকে প্রশিক্ষণের জন্য বাস্তব জীবনের ডেটা সেট প্রস্তুত করুন।


    গত কয়েকটি টিউটোরিয়ালে আমরা শিখেছি we learned what is a neural network, and how to write your own network in python from scratch. We learned how to use Tensorflow to quickly create a neural network and train it easily. Then we learned how to use Tensorboard to visualize the network for debugging and see real-time results। এখন আমরা বেসিক জ্ঞান দিয়ে সজ্জিত, আমরা বাস্তব জীবনের ডেটা থেকে শেখার জন্য মডেলগুলি তৈরি করতে শুরু করতে পারি। তবে তার আগে আমাদের ডেটা দরকার। এবং আমাদের এমন একটি ফর্ম্যাটে ডেটা পেতে হবে যা আমরা নেটওয়ার্কটিতে ফিড করতে পারি। এই টিউটোরিয়ালে, আমরা কীভাবে আসল তথ্য থেকে আমাদের নেটওয়ার্কের জন্য ডেটা সেট প্রস্তুত করতে শিখব।

    Let’s Get Some Data First

    এই টিউটোরিয়ালে, আমরা Kaggle dog vs cat কাগল কুকুর বনাম বিড়াল প্রতিযোগিতা দ্বারা সরবরাহিত একটি ডেটা সেট ব্যবহার করব। যা কেগলির ওয়েবসাইটে সর্বজনীনভাবে উপলভ্য আমরা সেই ডেটা সেটটি প্রস্তুত করব,  যাতে আমরা এটি নেটওয়ার্কে ফিড করতে পারি।

    You can get the dataset here -> https://www.kaggle.com/c/dogs-vs-cats/data

    the train.zip is একটি সংকুচিত ফোল্ডার যা কুকুর এবং বিড়ালের 25000 চিত্র ধারণ করে। ফাইলের নামটি এই ফর্ম্যাটে রয়েছে  [dog/cat].[sample number].jpg 

    সুতরাং ফাইলের নামটি পড়ে, আমরা এটি কুকুর বা বিড়াল যদি পেতে পারি। আসুন আমরা এই জিপটি ডাউনলোড করি এবং এটি আমাদের কার্যকরী ডিরেক্টরিতে সন্ধান করি যেখানে আমরা পাইথন স্ক্রিপ্টগুলি সংরক্ষণ করি।

    এখন আমরা সমস্ত চিত্র পড়তে এবং সেগুলি একটি  python তালিকায় সংরক্ষণ করতে পারি। এবং একে একে একে নেটওয়ার্কে এটি প্রয়োজন। তবে, এটি স্বয়ংক্রিয়ভাবে জিপটির আকার 500 Mb এবং এটি extracting করার পরে যদি আপনার প্রোগ্রামে পুরো ডেটাসেটটি লোড করতে হয় তবে এটি সম্ভবত GB খুব বেশি পরিমাণে RAM দখল করবে এবং একই সাথে আমাদের সমস্ত চিত্রের প্রয়োজনও হবে না। সুতরাং আমরা একটি ক্লাস তৈরি করব যা ব্যাচের মধ্যে এই চিত্রগুলির কয়েকটি পাবে, এর 20 টি চিত্র বলা যাক এবং তারপরে আমাদের নেটওয়ার্কটি প্রশিক্ষণ দেওয়ার পরে।

    সুতরাং আমরা একটি ক্লাস তৈরি করব যা এই চিত্রগুলির কয়েকটি সংগ্রহ করবে এবং একটি মিনি ব্যাচ তৈরি করবে, এর 20 টি চিত্র বলা যাক এবং তারপরে আমরা এটিতে আমাদের নেটওয়ার্কটি প্রশিক্ষণ দেব। তারপরে আমরা জেনারেটরটি ফোল্ডার থেকে পরবর্তী সেট চিত্র সংগ্রহ করি এবং অন্য একটি মিনি ব্যাচ তৈরি করি। ফোল্ডারে থাকা সমস্ত চিত্র সহ আমরা শেষ না হওয়া পর্যন্ত এটি চলতে থাকবে

    Okay, Let’s Create a Dataset Generatorঠিক আছে, আসুন একটি ডেটাসেট জেনারেটর তৈরি করি

    ঠিক আছে ধরে নিলাম আমাদের আপনার বর্তমান কার্যকরী ডিরেক্টরিতে “train.zip” ফাইল রয়েছে এবং নাম দেওয়া হয়েছে “train”, আসুন ডেটাসেট জেনারেটর তৈরি করি।

    Let’s add the libraries first

    import cv2 # to load the images
    import numpy as np # to do matrix mnupulations 
    from os.path import isfile, join # to manupulate file paths
    from os import listdir # get list of all the files in a directory
    from random import shuffle # shuffle the data (file paths)

    সুতরাং আমরা চিত্রটি লোড করতে opencv ওপেনসিভি ব্যবহার করছি, আমরা চিত্রটি লোড করার জন্য PIL  পিআইএলও ব্যবহার করতে পারি তবে আমি মনে করি ওপেনসিভি ব্যবহার করা আরও সহজ হবে। এবং আমরা কিছু চিত্রের ম্যানিপুলেশনগুলিও করতে চাই যাতে আমরা এর জন্য ওপেনসিভি ব্যবহার করব।

    Saparateing The Dataডেটা পরিস্কার করা

    কেগল ডেটা থেকে আমরা যে ডেটা পেয়েছি তা এটি একটি মিশ্র ডেটা। মানে কুকুর এবং বিড়ালের সমস্ত চিত্র একই ফোল্ডারে। এখন তাদের দুটি পৃথক ফোল্ডারে আলাদা করা যাক।

    We are going to write a function which will do that for us.

    def seperateData(data_dir):
        for filename in listdir(data_dir):
            if isfile(join(data_dir, filename)):
                tokens = filename.split('.')
                if tokens[-1] == 'jpg':
                    image_path = join(data_dir, filename)
                    if not os.path.exists(join(data_dir, tokens[0])):
                        os.makedirs(join(data_dir, tokens[0]))
                    copyfile(image_path, join(join(data_dir, tokens[0]), filename))
                    os.remove(image_path)
    এই ফাংশনটি ডেটা ডিরেক্টরিতে ক্যাট এবং কুকুর নামে 2 ফোল্ডার তৈরি করবে এবং ফাইলগুলিকে তাদের সংশ্লিষ্ট ফোল্ডারে সরিয়ে দেবে।

    এটি এর এককালীন কাজ এবং ভবিষ্যতে আমাদের এটি ব্যবহার নাও করতে হতে পারে, বারবার, আমরা এই ফাংশনটি করছি, আমাদের ডেটাসেট জেনারেটর শ্রেণির অংশ হিসাবে নয়।

    next, let’s create the DataSetGenerator class.

    class DataSetGenerator:
        def __init__(self, data_dir):
            self.data_dir = data_dir
            self.data_labels = self.get_data_labels()
            self.data_info = self.get_data_paths()
    
        def get_data_labels(self):
            data_labels = []
            for filename in listdir(self.data_dir):
                if not isfile(join(self.data_dir, filename)):
                    data_labels.append(filename)
            return data_labels
    
        def get_data_paths(self):
            data_paths = []
            for label in self.data_labels:
                img_lists=[]
                path = join(self.data_dir, label)
                for filename in listdir(path):
                    tokens = filename.split('.')
                    if tokens[-1] == 'jpg':
                        image_path=join(path, filename)
                        img_lists.append(image_path)
                shuffle(img_lists)
                data_paths.append(img_lists)
            return data_paths

    উপরের কোডে, আমরা ডেটাসেটজেনেটর নামে একটি শ্রেণি তৈরি করেছি, আমরা প্রারম্ভকালে আমরা ডাটাসেট ডিরেক্টরি পন্থাটি ডাটাবেস ডিরেক্টরিতে উপস্থিত সমস্ত ফোল্ডারগুলির তালিকা হিসাবে যুক্তি হিসাবে গ্রহণ করছি, তারপরে সেই স্বতন্ত্র ডিরেক্টরিগুলির মধ্যে ফাইল পাথের একটি তালিকা তৈরি করব using get_data_labels এবং get_data_paths পদ্ধতিটি নীচে লেখা আছে।

    এখন আসুন দেখে নেওয়া যাক get_data_labels এবং get_data_paths পদ্ধতিগুলির মধ্যে কী আছে। Get_data_labels পদ্ধতির অভ্যন্তরে, আমরা ডাটা ডিরেক্টরি ডিরেক্টরিতে সমস্ত আইটেমের নামের তালিকা পেতে listdir”  ফাংশনটি ব্যবহার করি। সুতরাং, এই ক্ষেত্রে, আমাদের তালিকায় দুটি আইটেম থাকবে “cat”, “dog”। এগুলি আমাদের ডেটাসেটের ক্লাস।

    এখন get_data_paths পদ্ধতির অভ্যন্তরে, আমরা আবার ডেটাসেট ডিরেক্টরিতে সমস্ত ফাইল এবং ফোল্ডারগুলি উপলব্ধ করতে "listdir" ফাংশনটি ব্যবহার করেছি। এবং লুপ জন্য একটি লুপ। তারপরে আমরা প্রতিটি পাথ পরীক্ষা করে দেখছি যদি এটি কোনও ফাইল বা ফোল্ডারের দিকে নির্দেশ করে। যদি এটি কোনও ফাইল হয় তবে আমরা পথের স্ট্রিংটিকে একটি  dot ->“.” দিয়ে বিভক্ত করছি এবং শেষ টোকেনটি পরীক্ষা করছি। সুতরাং এটি যদি কোনও জেপিজি ফাইল হয় তবে সর্বশেষ টোকেনটি "jpg" হবে। এটি কেবল চিত্র ফাইলগুলি নেওয়া এবং  temp টেম্পের ফাইলগুলির মতো ডিরেক্টরিতে উপস্থিত অন্য কোনও ফাইলকে  ignore উপেক্ষা করা।

    একবার আমরা এর "jpg" ফাইলটি নিশ্চিত হয়ে গেলে আমরা পুরো পথটি ডেটা ডিরেক্টরি এবং ক্লাস ডিরেক্টরিটি চিত্রের পথ হিসাবে যুক্ত করে দিয়েছিলাম।

    সুতরাং আমরা ইমেজ ফাইলের পাথ নিয়েছি এবং এটি একটি তালিকাতে যুক্ত করেছি img_lists। এবং আমরা সেই তালিকাটি মূল data_path ডেটা_পথ তালিকায় যুক্ত করেছি।

    এখন ডেটা_পথের তালিকায় কুকুরের সমস্ত চিত্রের তালিকাসমূহের সাথে দুটি এবং বিড়ালের জন্য সমস্ত চিত্রের পথের তালিকা সহ দুটি তালিকা থাকা উচিত।

    সুতরাং আমরা সমস্ত চিত্র ফাইলের পাথ এবং সংশ্লিষ্ট লেবেল পেয়েছি, এখন কী? কীভাবে চিত্রগুলি পাবেন ?, আমরা Python’s concept of generator, and the concept of yield পাইথনের জেনারেটরের ধারণাটি এবংmini-batches on the fly  উড়তে মিনি-ব্যাচগুলি তৈরি করার  ধারণাটি ব্যবহার করব এবং এটিতে আমাদের নেটওয়ার্ক প্রশিক্ষণের পরে তা মুছে ফেলব। সুতরাং এটি আমাদের পুরো ডেটাসেটটিকে মেমরিতে লোড করা এবং র‌্যামের বাইরে চলে যাওয়া এড়াতে সহায়তা করবে।

    Let’s Create A Mini-Batch Generator

    দেখুন আমরা কীভাবে আমাদের জন্য mini batches  দিয়ে একটি জেনারেটর তৈরি করতে পারি ।

    class DataSetGenerator:
        :
        :
        def get_mini_batches(self, batch_size=10, image_size=(200, 200), allchannel=True):
            images = []
            labels = []
            empty=False
            counter=0
            each_batch_size=int(batch_size/len(self.data_info))
            while True:
                for i in range(len(self.data_labels)):
                    label = np.zeros(len(self.data_labels),dtype=int)
                    label[i] = 1
                    if len(self.data_info[i]) < counter+1:
                        empty=True
                        continue
                    empty=False
                    img = cv2.imread(self.data_info[i][counter])
                    img = self.resizeAndPad(img, image_size)
                    if not allchannel:
                        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                        img = np.reshape(img, (img.shape[0], img.shape[1], 1))
                    images.append(img)
                    labels.append(label)
                counter+=1
    
                if empty:
                    break
                # if the iterator is multiple of batch size return the mini batch
                if (counter)%each_batch_size == 0:
                    yield np.array(images,dtype=np.uint8), np.array(labels,dtype=np.uint8)
                    del images
                    del labels
                    images=[]
                    labels=[]

    এই get_mini_batches পদ্ধতিতে, আমরা জেনারেটর তৈরি করছি। আমরা 3 টি চ্যানেল RGB or just gray scale image  চিত্র ব্যবহার করতে চাই কিনা তা যাচাই করতে আমরা  batch_size , output image_size and a flag allchannel  নিচ্ছি।

    আমরা প্রথমে প্রতিটি ক্লাসের জন্য batch_size in the batch_size কে বিভক্ত করেছি, যাতে আমরা প্রতিটি ক্লাস থেকে সমান পরিমাণে নমুনা নিই এবং প্রতিটি শ্রেণীর জন্য বর্তমান পুনরাবৃত্তির জন্য একটি counter কাউন্টার থাকে।

    তারপরে আমরা দুটি খালি তালিকার চিত্র এবং লেবেল তৈরি করেছি এবং লুপ চলাকালীন একটি অসীম শুরু করেছি, যখন ক্লাসগুলির কোনওটির কাছে প্রশিক্ষণের জন্য কোনও চিত্র নেই। লুপের অভ্যন্তরে আমরা প্রতিটি শ্রেণি থেকে একের পর এক চিত্র পেতে লুপের জন্য একটি অভ্যন্তর শুরু করি।

    সুতরাং কোনও ছবি লোড করার আগে, আমাদের অবশ্যই পরীক্ষা করতে হবে যে সেই শ্রেণীর তালিকায় কোনও image_path চিত্র_পথ রয়েছে কিনা, তাই আমরা পরীক্ষা করেছিলাম যে সেই নির্দিষ্ট শ্রেণির তালিকার দৈর্ঘ্যটি আমাদের পাল্টা মানের চেয়ে কম কিনা। যদি তা হয় তবে আমরা এটিকে খালি হিসাবে বিবেচনা করি এবং পরবর্তী ক্লাসে চালিয়ে যাব। যদি তা না হয় তবে আমরা empty flag কে মিথ্যা হিসাবে সেট করছি এবং image using cv2.imread() method ব্যবহার করে চিত্রটি লোড করছি।

    আমরা আমাদের সমস্ত নমুনা চিত্রগুলি একই আকারের হতে চাই, সুতরাং তাদের অনুপাতের অনুপাত পরিবর্তন না করে আমাদের সেগুলি একটি বর্গাকার চিত্রে আকার দিতে হবে। আমরা এটি করি যে আমরা  resizeAndPad রিসাইজএন্ডপ্যাড নামে আরও একটি ফাংশন ব্যবহার করতে যাচ্ছি, যা আমরা পরে ওপেনসিভি ব্যবহার করে বাস্তবায়ন করব।

    allchannel flag টি যদি এটি মিথ্যা হয় তবে আমরা cv2.cvtColor () পদ্ধতি ব্যবহার করে চিত্রটি ধূসর স্কেলে রূপান্তর করছি,

    অবশেষে লুপের পরে আমরা চিত্রের তালিকাতে এবং লেবেলের তালিকায় যুক্ত এক ধরণের চিত্র পেয়েছি আমরা পরবর্তী সেট চিত্রের জন্য কাউন্টারটিকে বাড়িয়েছি।

    এরপরে, আমরা খালিটির মানটি সত্য কিনা তা যাচাই করে যাচ্ছি এর অর্থ সমস্ত তালিকা লোড হয়ে গেছে তাই আমরা যখন লুপটি ভেঙে দেব। এবং যদি তা না হয় তবে আমরা পরবর্তী পদক্ষেপে যাব।

    এখন, প্রতিবার কাউন্টারটি each_batch_size র একাধিক যা পৃথক শ্রেণীর জন্য ব্যাচের আকার, আমরা ফলাফলগুলি দেব এবং ফলনের পরে, আমরা তাদের মেমরিটি প্রকাশ করতে মুছে ফেলব এবং বাকী ডেটা যুক্ত করতে থাকব পরবর্তী কল জন্য তালিকা।

    Creating The Image Resizer

    আমরা আমাদের আগের পদ্ধতিতে resizeAndPad() নামের চিত্র প্রতিরোধকের পদ্ধতিটি ব্যবহার করেছি, আমাদের আমাদের শ্রেণিটি নির্ধারণ করতে হবে।

    here it is
    class DataSetGenerator:
        :
        :
        def resizeAndPad(self, img, size):
            h, w = img.shape[:2]
    
            sh, sw = size
            # interpolation method
            if h > sh or w > sw:  # shrinking image
                interp = cv2.INTER_AREA
            else: # stretching image
                interp = cv2.INTER_CUBIC
    
            # aspect ratio of image
            aspect = w/h
    
            # padding
            if aspect > 1: # horizontal image
                new_shape = list(img.shape)
                new_shape[0] = w
                new_shape[1] = w
                new_shape = tuple(new_shape)
                new_img=np.zeros(new_shape, dtype=np.uint8)
                h_offset=int((w-h)/2)
                new_img[h_offset:h_offset+h, :, :] = img.copy()
    
            elif aspect < 1: # vertical image
                new_shape = list(img.shape)
                new_shape[0] = h
                new_shape[1] = h
                new_shape = tuple(new_shape)
                new_img = np.zeros(new_shape,dtype=np.uint8)
                w_offset = int((h-w) / 2)
                new_img[:, w_offset:w_offset + w, :] = img.copy()
            else:
                new_img = img.copy()
            # scale and pad
            scaled_img = cv2.resize(new_img, size, interpolation=interp)
            return scaled_img
    সুতরাং এখানে প্রথমে আমরা পরীক্ষা করেছি যে আমরা চিত্রটি সঙ্কুচিত করছি বা বড় করছি কিনা। Cv2.INTER_AREA পদ্ধতিটি চিত্র সঙ্কুচিত করার জন্য আরও ভাল যেখানে cv2.INTER_CUBIC হিসাবে রয়েছে
    এরপরে, আমরা এটি পরীক্ষা করে যাচ্ছি যে এটি কোনও horizontal image or a vertical image। এবং জিরো দিয়ে চিত্রটি padding প্যাডিং করুন যাতে এটি একটি বর্গাকার চিত্র হয়ে যায়।

    তারপরে আমরা প্রদত্ত আকার অনুযায়ী চিত্রটি স্কেল করতে cv2.resize পদ্ধতি প্রয়োগ করেছি।

    We are done!!

    এটি এখন আমরা সম্পন্ন করেছি আমরা আমাদের টেনসরফ্লো মডেলের জন্য মিনি ব্যাচ তৈরি করতে এই শ্রেণিটি ব্যবহার করতে পারি।যদি আমরা “./train”  যুক্তি দিয়ে separate  method পৃথক পদ্ধতিটি চালিত করি তবে এটি যেখানে ডিরেক্টরি, যেখানে কুকুর বনাম বিড়াল প্রশিক্ষণের চিত্রগুলি সংরক্ষণ করা হয়।

    এটি কুকুর এবং বিড়ালের চিত্রগুলিকে দুটি পৃথক ফোল্ডারে আলাদা করবে এবং আমাদের কেবল একবারের জন্য এটি প্রয়োজন।

    রিয়েল লাইফ ডেটা থেকে ডেটা সেট প্রস্তুত করার সম্পূর্ণ কোড

    এই টিউটোরিয়ালটির সম্পূর্ণ কোড এখানে

    import cv2
    import numpy as np
    from os.path import isfile, join
    from os import listdir
    from random import shuffle
    from shutil import copyfile
    import os
    import pickle
    
    
    def seperateData(data_dir):
        for filename in listdir(data_dir):
            if isfile(join(data_dir, filename)):
                tokens = filename.split('.')
                if tokens[-1] == 'jpg':
                    image_path = join(data_dir, filename)
                    if not os.path.exists(join(data_dir, tokens[0])):
                        os.makedirs(join(data_dir, tokens[0]))
                    copyfile(image_path, join(join(data_dir, tokens[0]), filename))
                    os.remove(image_path)
    
    
    
    class DataSetGenerator:
        def __init__(self, data_dir):
            self.data_dir = data_dir
            self.data_labels = self.get_data_labels()
            self.data_info = self.get_data_paths()
    
        def get_data_labels(self):
            data_labels = []
            for filename in listdir(self.data_dir):
                if not isfile(join(self.data_dir, filename)):
                    data_labels.append(filename)
            return data_labels
    
        def get_data_paths(self):
            data_paths = []
            for label in self.data_labels:
                img_lists=[]
                path = join(self.data_dir, label)
                for filename in listdir(path):
                    tokens = filename.split('.')
                    if tokens[-1] == 'jpg':
                        image_path=join(path, filename)
                        img_lists.append(image_path)
                shuffle(img_lists)
                data_paths.append(img_lists)
            return data_paths
    
        # to save the labels its optional incase you want to restore the names from the ids 
        # and you forgot the names or the order it was generated 
        def save_labels(self, path):
            pickle.dump(self.data_labels, open(path,"wb"))
    
        def get_mini_batches(self, batch_size=10, image_size=(200, 200), allchannel=True):
            images = []
            labels = []
            empty=False
            counter=0
            each_batch_size=int(batch_size/len(self.data_info))
            while True:
                for i in range(len(self.data_labels)):
                    label = np.zeros(len(self.data_labels),dtype=int)
                    label[i] = 1
                    if len(self.data_info[i]) < counter+1:
                        empty=True
                        continue
                    empty=False
                    img = cv2.imread(self.data_info[i][counter])
                    img = self.resizeAndPad(img, image_size)
                    if not allchannel:
                        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                        img = np.reshape(img, (img.shape[0], img.shape[1], 1))
                    images.append(img)
                    labels.append(label)
                counter+=1
    
                if empty:
                    break
                # if the iterator is multiple of batch size return the mini batch
                if (counter)%each_batch_size == 0:
                    yield np.array(images,dtype=np.uint8), np.array(labels,dtype=np.uint8)
                    del images
                    del labels
                    images=[]
                    labels=[]
    
        def resizeAndPad(self, img, size):
            h, w = img.shape[:2]
    
            sh, sw = size
            # interpolation method
            if h > sh or w > sw:  # shrinking image
                interp = cv2.INTER_AREA
            else: # stretching image
                interp = cv2.INTER_CUBIC
    
            # aspect ratio of image
            aspect = w/h
    
            # padding
            if aspect > 1: # horizontal image
                new_shape = list(img.shape)
                new_shape[0] = w
                new_shape[1] = w
                new_shape = tuple(new_shape)
                new_img=np.zeros(new_shape, dtype=np.uint8)
                h_offset=int((w-h)/2)
                new_img[h_offset:h_offset+h, :, :] = img.copy()
    
            elif aspect < 1: # vertical image
                new_shape = list(img.shape)
                new_shape[0] = h
                new_shape[1] = h
                new_shape = tuple(new_shape)
                new_img = np.zeros(new_shape,dtype=np.uint8)
                w_offset = int((h-w) / 2)
                new_img[:, w_offset:w_offset + w, :] = img.copy()
            else:
                new_img = img.copy()
            # scale and pad
            scaled_img = cv2.resize(new_img, size, interpolation=interp)
            return scaled_img
    
    
    if __name__=="__main__":
        seperateData("./train")


  • 0 comments:

    Post a Comment

    New Research

    Attention Mechanism Based Multi Feature Fusion Forest for Hyperspectral Image Classification.

    CBS-GAN: A Band Selection Based Generative Adversarial Net for Hyperspectral Sample Generation.

    Multi-feature Fusion based Deep Forest for Hyperspectral Image Classification.

    ADDRESS

    388 Lumo Rd, Hongshan, Wuhan, Hubei, China

    EMAIL

    contact-m.zamanb@yahoo.com
    mostofa.zaman@cug.edu.cn

    TELEPHONE

    #
    #

    MOBILE

    +8615527370302,
    +8807171546477