• TensorFlow দিয়ে ইমেজ ক্লাসিফায়ার তৈরি

    TensorFlow দিয়ে ইমেজ ক্লাসিফায়ার তৈরি

    এই সেকশনে আমরা, অনেক রকম মানুষের বিভিন্ন রকম হাতের লেখা ওয়ালা কিছু নাম্বার/ডিজিট এর ফটো কালেকশন দিয়ে একটা নিউরাল নেটওয়ার্ক-কে ট্রেইন করিয়ে তারপর কিছু টেস্ট ফটো দিয়ে সেগুলোর সঠিক ক্লাসিফিকেশন জানার চেষ্টা করবো। সহজ ভাবে বলতে - "হ্যান্ড রিটেন ডিজিট ক্লাসিফিকেশন প্রব্লেম"।
    এই টিউটোরিয়ালে আমরা কনভলিউশনাল নিউরাল নেটওয়ার্ক মডেল ব্যবহার করছি না। বরং সিঙ্গেল লেয়ারের লিনিয়ার মডেল ব্যবহার করবো। অর্থাৎ একটি ইনপুট লেয়ার এবং একটি আউটপুট লেয়ার থাকবে, কিন্তু ইনপুট লেয়ারে প্রথম দিকের উদাহরণ এর মত কয়েকটি না বরং অনেক গুলো নিউরন থাকবে। আর আউটপুট লেয়ারে থাকবে ১০টি নিউরন। ১০ ধরনের ডিজিট ক্লাসিফিকেশনের জন্য। এতে করে আমাদের TensorFlow দিয়ে কাজ করার কমন কিছু স্টেপ সম্বন্ধে পরিষ্কার ধারনা আসবে। তবে হ্যাঁ, এই লিনিয়ার ক্লাসিফায়ারও যথেষ্ট ভালো মতই ডিজিট ক্লাসিফিকেশন করতে পারবে আশা করা যায়। অন্তত ৮৫-৯০% সঠিক ক্লাসিফাই করতে পারবে। এই টিউটোরিয়ালের পর আমরা একই সমস্যা আরও ইফেক্টিভ ভাবে সমাধানের জন্য এবং অ্যাকিউরেসি লেভেল আরও বাড়ানোর জন্য কনভলিউশনাল নিউরাল নেটওয়ার্ক মডেল ব্যবহার করবো। যা হোক, এখন আমরা ধাপে ধাপে সব গুলো কাজ করবো এবং লেয়ার তৈরি করবো এবং তার মাঝে মাঝেই কিছু নতুন টার্ম আসবে, সেগুলোর প্রয়োজনীয়তা এবং সংজ্ঞা জানবো।
    প্রথমেই আমরা কিছু রেডিমেড ডাটা সেট নিয়ে কাজ করবো। অর্থাৎ ডিজিট ক্লাসিফিকেশন শিখতে গিয়ে আমাদের অনেক অনেক ইমেজ দরকার পরবে আমাদের মডেলকে ট্রেনিং দেয়ার জন্য, তাই না? এমনকি ট্রেনিং ডাটাগুলো লেবেল্ড (কোন ফটো কোন ডিজিট তার একটা ম্যাপিং) হতে হবে। নাহলে ট্রেনিং হবে ক্যামনে? এখন নিউরাল নেটওয়ার্ক শিখতে গিয়ে যদি মাসের পর মাস সময় দিয়ে শুধু ডাটাই রেডি করতে হয় তাহলে ক্যামনে কি? মজার বিষয় হচ্ছে, TensorFlow -এর সাথেই এরকম কিছু রেডিমেড ডাটা থাকে এবং যেগুলো চাইলে আমরা import করে সেগুলোর উপর কাজ করতে পারি। অন্তত আসল জিনিষ শেখার সময় আমাদের পুরো সময়টা ডাটা প্রি-প্রসেসিং -এ নষ্ট হচ্ছে না। ফোকাস থাকবে মডেল ডেভেলপমেন্টে। যা হোক, এই ডাটাবেজটার নাম হচ্ছে
    MNIST ডাটাবেজ/ডাটাসেট।
    এই টিউটোরিয়ালের জন্য আমরা Jupyter Notebook ব্যবহার করবো। এতে করে ধাপে ধাপে আলোচনা করে করে আগানো যাবে এবং আগের ধাপে রান করা কোড পরের ধাপেও অ্যাক্সেস করা যাবে। jupyter Notebook সম্পর্কে ধারনা না থাকলে একটু অন্য কোথাও থেকে আপাতত দেখে আসতে পারেন। এটা তেমন কিছু না। একটা ওয়েব অ্যাপ। এতে করে ব্রাইজারের মধ্যে একটা পেজে কোড এবং বাংলা ইংলিশ মিলিয়ে লেখা যায় এবং কোড গুলোকে রানও করা যায়। আর পুরো ডকুমেন্টের রানটাইম একটাই থাকে। এটাও খুব সহজে প্যাকেজ আকারেই ইন্সটল করা যায় এবং একটা কমান্ড দিয়েই রান করানো যায়। কথা না বাড়িয়ে শুরু করা যাক।
    যদিও শেষের দিকে পুরো প্রোগ্রামের একটা স্ক্রিপ্ট ভার্সন থাকবে যেটা স্বাভাবিকভাবে নোটবুকের বাইরেও রান করানো যাবে।
    # Cell 1
    %matplotlib inline
    import matplotlib.pyplot as plt
    import tensorflow as tf
    import numpy as np
    from sklearn.metrics import confusion_matrix
    উপরের ব্লক নিয়ে কিছু বলার দরকার আছে কি? সব চেনা জিনিষ, একটা বাদে। confusion_matrix ব্যবহার করে আমরা একধরনের স্পেশাল ম্যাট্রিক্স তৈরি ও ডিসপ্লে করতে পারি যার মাধ্যমে আমরা কিছু রিলেটেড এরর এর বৈশিষ্ট্য সম্পর্কে একটা ভিজুয়াল ধারনা পাবো। এটার স্টেপ আসা মাত্রই এর দরকারটাও বোঝা যাবে। যদিও এটা অপশনাল স্টেপ। আমাদের মুল মডেল তৈরিতে এটার গুরুত্ব নাই, বরং Accuracy বাড়াতে এবং সমস্যার উপর একটা স্পষ্ট ধারনা আনতে সাহায্য করবে এই ম্যাট্রিক্স। অর্থাৎ, সমস্যা নিয়ে ভালো অব্জারভেশন করতে চাইলে এগুলো লাগে। আরেকটা জিনিষ - %matplotlib inline যার মাধ্যমে জুপিটার নোটবুকের চলতি ডকুমেন্টটির মধ্যেই প্লটিং গুলো ডিসপ্লে করার কথা বলা হচ্ছে। তো নোটবুকের প্রথম সেলে এই কোড লিখে সেলটি এক্সিকিউট করে ফেলি।
    এরপর আমাদের ডাটাগুলোকে লোড করতে হবে, এর জন্য নিচের কোড টুকু ব্যবহার করতে পারি অর্থাৎ পরের সেলে লিখে সেলটি এক্সিকিউট করতে পারি,
    # Cell 2
    from tensorflow.examples.tutorials.mnist import input_data
    data = input_data.read_data_sets("data/MNIST/", one_hot=True)
    এর মাধ্যমে ১২ মেগাবাইট সাইজের ডাটাসেটটি ডাউনলোড হবে যদি data/MNIST/ পাথে আগে থেকেই ডাটাসেটটি না থাকে।

    ডাটা বুঝে নেয়া

    পুরো ডাটাসেটে যথাযথ ক্লাস (কোনটা কোন ডিজিট) ম্যাপ করা ৭০০০০ ইমেজ আছে যার মধ্যে ৫৫০০০ হচ্ছে ট্রেনিং ইমেজ, ১০০০০ হচ্ছে টেস্ট ইমেজ এবং ৫০০০ হচ্ছে ভ্যালিডেশন ইমেজ। অর্থাৎ পুরো ডাটাসেটটি ৩টি সাবসেটে বিভক্ত। কিছু ডাটা ট্রেনিং এর জন্য, কিছু ডাটা ভ্যালিডেশনের জন্য, আর কিছু ডাটা হচ্ছে ফাইনাল মডেলকে টেস্ট করার জন্য। এই সাবসেট গুলো মিউচুয়ালি এক্সকুসিভ অর্থাৎ একটি সেটের ডাটা আরেকটি সেটের মধ্যে নাই। অর্থাৎ কমন কোন এলিমেন্ট এই ৩টি সেটের মধ্যে নাই। পরীক্ষা করে দেখতে পারি নিচের কোড ওয়ালা সেলটি এক্সিকিউট করে,
    # Cell 3
    print("Size of:")
    print("- Training-set:\t\t{}".format(len(data.train.labels)))
    print("- Test-set:\t\t{}".format(len(data.test.labels)))
    print("- Validation-set:\t{}".format(len(data.validation.labels)))
    আউটপুট,
    Size of:
    - Training-set: 55000
    - Test-set: 10000
    - Validation-set: 5000
    এই টিউটোরিয়ালে আমরা ভ্যালিডেশন সেটের ব্যবহার করবো না। যা হোক, Cell 2 এর কোডের read_data_sets মেথডের দ্বিতীয় প্যারামিটার নিয়ে একটু কথা বলি. one_hot=True পাঠিয়ে আমরা বলছি যে এই ডাটাসেট এর লেবেল (ফটোর সাপেক্ষে সঠিক উত্তর/ডিজিট) গুলোকে আমরা এই ফরম্যাটে চাই। এই ফরম্যাট ডেসিম্যাল ডিজিটের বাইনারি রিপ্রেজেন্টেশনের মতই কিন্তু একটু অন্যভাবে রিপ্রেজেন্ট করে। মাত্র একটি বিট কে হাই বা 1 করে সেই ডিজিটের অবস্থান প্রকাশ করা হয়। নিচের উদাহরণ দেখলেই ব্যাপারটি সহজেই বোঝা যাবে। যেমন 0 এবং 5 এর বাইনারি রিপ্রেজেন্টেশন হয় নিচের মত,
    আর One-Hot Vector প্রেজেন্টেশন হয় নিচের মত,
    অর্থাৎ ডিজিটটি যদি 5 হয় তাহলে ৫টি বিট ওয়ালা একটি ভেক্টরের ৫নাম্বার বিটটি হাই অর্থাৎ 1 সেট করে দেয়া হয়। তো, আমাদের আলোচনায় ডাউনলোড করা হাতের লেখার ফটো গুলোর লেবেল গুলো আসছে এই ফরম্যাটে। আমরা ডাটাসেট থেকে প্রথম ৫টি ফটোর লেবেল গুলোর One-Hot Vector রিপ্রেজেন্টেশন দেখতে পারি নিচের মত করে,
    # Cell 4
    data.test.labels[0:5, :]
    আউটপুট আসবে, নিচের মত,
    array([[ 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
    [ 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
    [ 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
    [ 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
    [ 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.]])
    তাহলে আমরা দেখে দেখেই বলে দিতে পারি প্রথম ৫টি ডিজিটের লেবেল বা নাম কি। প্রথমটার ৭নাম্বার বিটটি হাই, তাই এটি 7. দ্বিতীয়টির ২ নাম্বার বিট হাই, অর্থাৎ এটি 2 লেখা একটি ফটোর লেবেল/নাম।
    আমরা চাইলে একই কাজটা কোড লিখেও করতে পারি। যেমন, নিচের লাইন খেয়াল করুন,
    # Cell 5
    data.test.cls = np.array([label.argmax() for label in data.test.labels])
    এখানে লুপ চালিয়ে প্রত্যেকটি লেবেল ভেক্টরকে নিয়ে তার উপর argmax() মেথডটি অ্যাপ্লাই করা হয়েছে। এই মেথডের কাজ হচ্ছে একটি ভেক্টরের মধ্যে যে বিটটি হাই থাকবে তার ইনডেক্স রিটার্ন করবে। হয়ে গেলো? আমরা লেবেল গুলোর One-Hot Vector টাইপের রিপ্রেজেন্টেসন থেকে খুব সহজেই সঠিক ডিজিট নাম্বারটা পেতে পারি। এই পুরো কনভার্সনটা একটা numpy array তে কনভার্ট করে স্টোর করা হচ্ছে।
    এখন যদি আমরা data.test.cls ভ্যারিয়েবলের প্রথম ৫টি এলিমেন্ট দেখি তাহলে নিচের মত আউটপুট পাবো,
    # Cell 6
    data.test.cls[0:5]
    array([7, 2, 1, 0, 4])
    এতক্ষণে One-Hot Vector প্রেজেন্টেশন এবং argmax মেথডের কাজ বোঝা গেছে নিশ্চয়ই?

    ডাটা ডাইমেনশন

    ডাটা ডাইমেনশন সম্পর্কে স্বচ্ছ ধারনা রাখতে হবে মাথায়। কোন ম্যাট্রিক্স বা টেনসরের ডাইমেনশন এর প্রসঙ্গ আসা মাত্রই যাতে কল্পনায় স্পষ্ট একটা ভিউ আসে ওই ডাটা অবজেক্টটার। তাহলে সব কিছু সহজ মনে হবে। যাই হোক, এরকম কিছু ডাইমেনশনকে আমরা কিছু ভ্যারিয়েবলে স্টোর করি এবার এবং সেলটি এক্সিকিউট করে নেই,
    # Cell 7
    # We know that MNIST images are 28 pixels in each dimension.
    img_size = 28
    # Images are stored in one-dimensional arrays of this length.
    img_size_flat = img_size * img_size
    # Tuple with height and width of images used to reshape arrays.
    img_shape = (img_size, img_size)
    # Number of classes, one class for each of 10 digits.
    num_classes = 10
    img_size ভ্যারিয়েবলে আমাদের আলোচ্য ফটোগুলোর ডাইমেনশন স্টোর করছি। MNIST ডাটাসেটের ফটো গুলো 28x28 সাইজের ফটো। আসলে ইমেজের কন্টেক্সট থেকে বলতে, 28x28x1 সাইজের অর্থাৎ ফটো গুলো সাদা কালো এবং এর কালার চ্যানেল একটাই। রঙ্গিন ফটো হলে এদের ডাইমেনশন হত 28x28x3। RGB তিনটা রঙের তিনটা চ্যানেল এবং প্রত্যেক চ্যানেলের জন্য 28x28 সাইজের একগাদা পিক্সেল ভ্যালু। যা হোক, দ্বিতীয় ভ্যারিয়েবলে আমরা প্রত্যেকটি ইমেজের ফ্ল্যাট রিপ্রেজেন্টশন স্টোর করছি অর্থাৎ 28x28 সাইজের একটি ফটোর সবগুলো পিক্সেলকে যদি স্টোর করতে চাই তাহলে আমাদের img_size * img_size সাইজের একটি ওয়ান ডাইমেনশনাল অ্যারে বা ভেক্টর লাগবে। একটি টাপলে ইমেজের সেইপকে স্টোর করছি। আর শেষের ভ্যারিয়েবলে স্টোর করছি আমাদের যতগুলো আউটপুট ক্লাস দরকার সেই সংখ্যাটা। আমাদের ১০ ধরনের ক্লাসিফিকেশন দরকার, কারন ১০টাই ডিজিট দুনিয়াতে।
    এ অবস্থায় একটু খুত খুতে লাগতে পারে এটা ভেবে যে - এইযে ফটো গুলো ইম্পরট করলাম এবং সেগুলোর উপর নাকি আবার কাজ করবো। সেগুলো আসলে দেখতে কেমন? ক্লিয়ার ভিউ তো লাগবে নাকি? ;)
    নিচের কোড ব্লকটি পুরো একটি হেল্পার ফাংশন যার মাধ্যমে আমরা MNIST ডাটাসেটের ইমেজ গুলোকে রেন্ডার বা ডিসপ্লে করতে পারবো যেকোনো সময়। এখানে একটি 3x3 গ্রিডে মোট ৯টি ফটো এবং সেগুলোর সঠিক লেবেল ডিসপ্লে করানোর ব্যবস্থা করা হয়েছে।
    # Cell 8
    def plot_images(images, cls_true, cls_pred=None):
    assert len(images) == len(cls_true) == 9
    # Create figure with 3x3 sub-plots.
    fig, axes = plt.subplots(3, 3)
    fig.subplots_adjust(hspace=0.3, wspace=0.3)
    for i, ax in enumerate(axes.flat):
    # Plot image.
    ax.imshow(images[i].reshape(img_shape), cmap='binary')
    # Show true and predicted classes.
    if cls_pred is None:
    xlabel = "True: {0}".format(cls_true[i])
    else:
    xlabel = "True: {0}, Pred: {1}".format(cls_true[i], cls_pred[i])
    ax.set_xlabel(xlabel)
    # Remove ticks from the plot.
    ax.set_xticks([])
    ax.set_yticks([])
    তো, উপরের এই ফাংশনকে কাজে লাগিয়ে আমরা কিছু ফটো এবং সেগুলোর সাপেক্ষে সঠিক লেবেল রেন্ডার করে দেখি,
    # Cell 9
    # Get the first images from the test-set.
    images = data.test.images[0:9]
    # Get the true classes for those images.
    cls_true = data.test.cls[0:9]
    # Plot the images and labels using our helper-function above.
    plot_images(images=images, cls_true=cls_true)
    এই অবস্থায় নোটবুকের সেলটি এক্সিকিউট করলে নিচের মত আউটপুট আসবে,

    গ্রাফ তৈরি

    আগেই বলা হয়েছে, TensorFlow দিয়ে কাজ করতে হলে প্রথমেই একটি পুরনাঙ্গ কম্পিউটেশনাল গ্রাফ তৈরি করতে হয়। এরপর পুরো গ্রাফকে এক সাথে এক্সিকিউট করা যায়। এতে করে পাইথনে আলাদা আলাদা করে ক্যালকুলেশন গুলো লিখে এক্সিকিউট করালে যেমন টাইম বা অন্য কমপ্লেক্সিটি হতে পারতো, তার চেয়ে অনেক ইফেক্টিভলি ক্যালকুলেশন গুলো হয়। গ্রাফে আরও সুবিধা হচ্ছে স্বয়ংক্রিয় ভাবে গ্র্যাডিয়েন্ট ডিসেন্ট বের করা যায় যাতে করে মডেলের ভ্যারিয়েবল (ওয়েট, বায়াস) গুলোকে অপ্টিমাইজ করা যায় সহজেই। যেহেতু পুরো গ্রাফ জুড়ে অনেক গুলো কম্পিউটেশন থাকে এতে করে ডেরিভ্যাটিভ এর চেইন রুল এর মাধ্যমে খুব দ্রুত এবং সহজে পুরো গ্রাফের গ্র্যাডিয়েন্ট ডিসেন্ট বের করা যায়।
    এ অবস্থায় আমরা আবার জানবো - একটা TensorFlow গ্রাফ মূলত কি কি নিয়ে গঠিতঃ
    ১) প্লেসহোল্ডার ভ্যারিয়েবল - যার মাধ্যমে গ্রাফে ইনপুট দেয়া হয়
    ২) মডেল ভ্যারিয়েবল - ওয়েট, বায়াস ইত্যাদি; মূলত ট্রেনিং করিয়ে এগুলোকে অপ্টিমাইজ করেই একটা ইফিসিয়েন্ট মডেল তৈরি করা হয়
    ৩) মডেল - সহজ কথায় একটি ম্যাথেম্যাটিক্যাল ফাংশন যেখানে প্লেসহোল্ডারের মাধ্যমে ইনপুট দিয়ে এবং মডেল ভ্যারিয়েবলের সমন্বয়ে আউপুটপুট পাওয়া যায়
    ৪) Cost - এই মানের উপর ভিত্তি করে মডেল ভ্যারিয়েবল গুলোর অপটিমাইজেশনের দিক নির্দেশনা দেয়া হয়
    ৫) অপটিমাইজেশন মেথড - এই মেথড মূলত Cost কে মাথায় রেখে মডেল ভ্যারিয়েবল গুলোকে আপডেট করে।

    প্লেস হোল্ডার তৈরিঃ
    আগেও একবার বলা হয়েছে - এর মাধ্যমে গ্রাফে ইনপুট দেয়া হয়। যেমন, প্লেসহোল্ডারকে মেনে এক এক বার এক এক সেট ইনপুট দেয়া যাবে গ্রাফে। অনেকে বলেন গ্রাফকে ফিড করানো। তো, আমরা আসলে গ্রাফে কি ইনপুট দিবো? ইমেজ বা হাতের লেখা ওয়ালা ফটো গুলোকে, তাই তো? আমরা প্রথমবার হয়ত ১০০টা ইমেজ গ্রাফে ইনপুট দিলাম। পরেরবার আরও ২০০ দিলাম। তাই, ইমেজ ইনপুট দেয়ার জন্য একটা প্লেসহোল্ডার ভ্যারিয়েবল থাকলে ভালো। এই প্লেসহোল্ডার হবে Tensor টাইপের। Tensor মানে? মাল্টিডাইমেনশনাল ভেক্টর বা ম্যাট্রিক্স :) Tensor এর ডাটাটাইপ হবে float32. আর এর সেইপ হবে [None, img_size_flat] None মানে হচ্ছে এই টেনসরটি যেকোনো সংখ্যক ইমেজ নিতে পারবে যে ইমেজ গুলো কিনা এক একটি ফ্ল্যাট অ্যারে অর্থাৎ সবগুলো পিক্সেলের ফ্ল্যাট ভেক্টর তথা আমাদের একটু আগের স্টেটমেন্ট অনুযায়ী img_size_flat. অর্থাৎ স্টেটমেন্টটি হবে,

    # Cell 10
    x = tf.placeholder(tf.float32, [None, img_size_flat])
    আরেকবার বলি - যেমন উপরের স্টেটমেন্ট এর প্লেসহোল্ডারে যদি আমরা যেকোনো সময় মাত্র দুটি 28x28 সাইজের ফটোকে ইনপুট হিসেবে দিয়ে গ্রাফ এক্সিকিউট করি তাহলে উপরের স্টেটমেন্টার অভ্যন্তরীণ চেহারা হবে এরকম, x = tf.placeholder(tf.float32, [2, 784]) এবং ডাটার চেহারা হবে [[p00, p01 .... p0783], [p10, p11 .... p1783]]. pxx হচ্ছে পিক্সেল ভ্যালু।
    এবার আরও একটা প্লেসহোল্ডার নেবো যেখানে সময় মত ইনপুট দেবো, একটু আগে ইনপুট দেয়া ইমেজ গুলোর সঠিক লেবেল গুলোকে। এই প্লেসহোল্ডার ভ্যারিয়েবলের সেইপ হবে [None, num_classes] টাইপের? কেন? None মানে যেকোনো সংখ্যক লেবেল সেট নিতে পারবে আর প্রত্যেকটা লেবেল সেট হবে num_classes অর্থাৎ 10 লেন্থ এর ভেক্টর। আগের প্লেসহোল্ডার ভ্যারিয়েবলটির নাম ছিল x এবং এই প্লেসহোল্ডার ভ্যারিয়েবলটির নাম y_true.
    # Cell 11
    y_true = tf.placeholder(tf.float32, [None, num_classes])
    এবার আমাদের আরেকটি প্লেসহোল্ডার দরকার পরবে। এর মধ্যে দেয়া হবে x প্লেসহোল্ডারের প্রত্যেকটি ইমেজের জন্য এর ট্রু ক্লাস। অর্থাৎ এটার ধরন হবে ইন্টিজার টাইপের। কারন ট্রু ক্লাস গুলো তো (0,1,2,3 ... 9) এরকম. এর সেইপ হবে [None] অর্থাৎ, এই প্লেসহোল্ডারটি একটি ওয়ান ডাইমেনশনাল ভেক্টর কিন্তু যার লেন্থ হতে পারে যেকোনো সংখ্যক। অর্থাৎ একটি ইমেজের ক্ষেত্রে এটি শুধুমাত্র ওই ইমেজেটির ট্রু ক্লাস/লেবেল হোল্ড করবে আবার ৫০টা ইমেজের জন্য ৫০টা ট্রু ক্লাস হোল্ড করবে। এই আর কি,
    # Cell 12
    y_true_cls = tf.placeholder(tf.int64, [None])
    এখন পর্যন্ত x, y_true এবং y_true_cls এই তিনটা প্লেসহোল্ডার ভ্যারিয়েবলকে মাথার মধ্যে পরিষ্কার ভাবে স্টোর করুন। দরকার হলে এই সেকশনের শুরু থেকে আরেকবার পরে আসুন।
    এবার আসি মডেল ভ্যারিয়েবলেঃ
    এই পোস্টের একদম শুরুতে যে নিউরাল নেটওয়ার্কের উদাহরণ দেয়া হয়েছে সেটা মনে আছে? ওখানে কিন্তু আমরা ট্রেইন করে করে কিছু ওয়েট ঠিক করেছিলাম যেগুলোর উপর ভিত্তি করেই পরবর্তীতে ওই মডেল নতুন ইনপুট নিয়ে ওয়েটের সঙ্গে নানা রকম ক্যালকুলেশন করে আউটপুট দিত। এই নিউরাল নেটওয়ার্কে শুধু নতুন যুক্ত হয়েছে বায়াস। অর্থাৎ ওয়েট থাকে Edge -এ আর বায়াস থাকে Node -এ বা নিউরনে। যাই হোক, এই ওয়েট আর বায়াস-ই কিন্তু মুল ভ্যারিয়েবল, যেগুলোর মান এই মডেল অ্যাডজাস্ট করে নেয় ট্রেনিং করার সময়। আর এই দুটো ভ্যারিয়েবলকেই মডেল ভ্যারিয়েবল বলা হয়ে থাকে। এখন আমরা আমাদের মডেলের এই দুটো ভ্যারিয়েবলকে ডিফাইন করবো। এগুলো কিন্তু প্লেসহোল্ডার নয় যে এগুলোর মান বাইরে থেকে ইনপুট হবে। বরং এগুলো নর্মাল ভ্যারিয়েবল যেগুলো কিনা ট্রেনিং চলাকালীন অবস্থায় ক্যালকুলেশনের মধ্যে সময়ে সময়ে অ্যাডজাস্ট বা অপ্টিমাইজড হবে।

    শুরুতেই আমরা ওয়েট ভ্যারিয়েবল ডিফাইন করি। একদম শুরুর উদাহরণে যেমন আমরা কিছু ওয়েট ডিফাইন করেছিলাম র‍্যান্ডোম ভ্যালু দিয়ে এবং তারপর ট্রেইন শুরু করেছিলাম। এবার আমরা সবগুলো ওয়েটের মান ধরব 0. ভয়ের কিছু নাই, ট্রেনিং শুরু হওয়া মাত্রই এগুলো বদলে ঠিক ঠাক ভ্যালুর দিকেই আগাবে। যা হোক, এদের সেইপ হবে [img_size_flat, num_classes]।
    # Cell 13
    weights = tf.Variable(tf.zeros([img_size_flat, num_classes]))
    কেন এরকম হল? আবার সেই প্রথম উদাহরণের কথাই আনা যায় - ওখানে যেমন এক পাশে তিনটা ইনপুট নিউরন ছিল এবং আউটপুট লেয়ারে একটা নিউরন ছিল। আর আমাদের দরকার হয়েছিল 3x1 ওয়েট ম্যাট্রিক্স। ঠিক এই মডেলও যেহেতু লিনিয়ার মডেল (Accuracy নিয়ে মাথা ঘামাচ্ছি না আমরা, এবং বলছি না যে ক্লাসিফিকেশনের জন্য এটা ভালো কোন মডেল) আর এর প্রথম (ইনপুট) লেয়ারে 784 টা নিউরন আছে এবং আউটপুট লেয়ারে 10 টা নিউরন আছে তাই এর সেইপ এরকম। পরিষ্কার? :)
    এ অবস্থায় আমার মনে হয় আমাদের মডেলটার একটা ভিজুয়ালাইজেশন দরকার। নিচে দিয়ে দিলাম,
    এবার ডিফাইন করি bias এর জন্য ভ্যারিয়েবল। আগেও বলা হয়েছে, বায়াস থাকে নোডে বা নিউরনে, অর্থাৎ যখন একটি নিউরনের জন্য ওয়েট এবং এইজের ক্যালকুলেশন শেষ হয়ে নোডে জমা হয় তখন এর সাথে যোগ হয় bias. তো আমাদের ইনপুট লেয়ারে একগাদা নিউরন থাকলেও আউটপুট লেয়ারে কিন্তু ১০টাই নিউরন। তাই এই ডাটা অবজেক্ট (টেনসর বা ভেক্টর) এর সেইপ হবে [num_classes]। আর স্টেটমেন্ট হবে নিচের মত,
    # Cell 14
    biases = tf.Variable(tf.zeros([num_classes]))

    মডেল

    খুব সহজ ভাবে বলতে গেলে, আমাদের এই ম্যাথেম্যাটিক্যাল মডেলটি প্লেস হোল্ডার ভ্যারিয়েবল x এর মধ্যে থাকা ইমেজ গুলোর সাথে weights গুন করে এবং শেষে bias যোগ করে। আর এর রেজাল্টটি হয় একটি ম্যাট্রিক্স যার সেইপ হবে, [num_images, num_classes]. কারন কি? কারন হচ্ছে, ইনপুট লেয়ারের ডাটা ম্যাট্রিক্স বা x এর সেইপ হচ্ছে [num_images, img_size_flat] (None এর জায়গায় যেকোনো সংখ্যক ইমেজ দেয়া যাবে, মনে আছে? ধরলাম num_images সংখ্যক দিয়েছি), আর weights এর সেইপ হচ্ছে [img_size_flat, num_classes]. XxY আর YxZ গুন করলে XxZ -ই হয় :) তাই রেজাল্ট ম্যাট্রিক্সের সেইপ হবে, [num_images, num_classes]. আর এই ম্যাট্রিক্সের প্রত্যেকটি row এর সাথে bias ভেক্টর যোগ হয়। অর্থাৎ যদি ম্যাট্রিক্সে শুধু দুটো ইমেজের ডাটা থাকে সেগুলো হবে এরকম - [[c00, c01, c02, c03, c04, c05, c06, c07, c08, c09],[c10, c11, c12, c13, c14, c15, c16, c17, c18, c19]]. আর এগুলোর সাথে bias (দেখতে এমন - [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9]) ভেক্টর যোগ করা যাবে খুব সহজে নিচের স্টেটমেন্ট দিয়ে।
    # Cell 15
    logits = tf.matmul(x, weights) + biases
    জেনে রাখা ভালো - logits নামটি TensorFlow নিয়ে কাজ করার সময় একটা কনভেনশনাল নাম মাত্র। তো, logits হচ্ছে একটা ম্যাট্রিক্স যার row সংখ্যা = num_images এবং কলাম সংখ্যা = num_classes। আর তাই এভাবে বলা যায় - i তম row (ইমেজ) এর সাথে j তম কলাম (ক্লাস) -এর সম্পর্ক দেখেই ওই ইমেজের ক্লাস নির্ধারণ সম্ভব।
    তবে সমস্যা হচ্ছে এখানে একটি row এর কলাম ভিত্তিক ভ্যালু গুলোর মান নানা রকম অর্থাৎ ছোট বড় মিলিয়ে। তাই কলামের ভ্যালু গুলো এই অবস্থায় সরাসরি দেখে ক্লাস বলা একটু টাফ। তাই আমরা যেটা করতে পারি, logits ম্যাট্রিক্সের প্রত্যেকটা row এর ভ্যালুগুলোকে নরমালাইজ করতে পারি যাতে করে পুরো একটা row এর ১০টি ভ্যালুর সমষ্টি ১ হয়। এবং প্রত্যেকটি ভ্যালু ০ থেকে ১ এর মধ্যে হয়। তাহলে এটাকে আমরা একটা প্রোব্যাবিলিটি ডিস্ট্রিউবিউশন বলতে পারি। যাই হোক, এই কাজটা করার জন্য আমরা softmax মেথডের সাহায্য নেবো নিচের মত,
    # Cell 16
    y_pred = tf.nn.softmax(logits)
    তার মানে এবার প্রত্যেকটা row (প্রত্যেকটা ইমেজ) এর ১০ টা করে ভ্যালু (ক্লাস) হবে ০ থেকে ১ এর মধ্যে এবং যেটার ভ্যালু বেশি হবে অর্থাৎ প্রোব্যাব্লিলিটি সবচেয়ে বেশি হবে ধরা যায় ওই row (ইমেজ) এর ক্লাস/লেবেল ওইটা। ওইটা বলতে ১০টা কলামের ওই নাম্বার কলাম। তো, যে কলামের ভ্যালু বেশি সেই কলামের ইনডেক্স পেতে আমরা আগেও একবার ব্যবহার করেছি argmax মেথড। তাহলে আবার আমরা y_pred এর উপর এই মেথডের ইমপ্লিমেন্টেশন করে ফেলি।
    # Cell 17
    y_pred_cls = tf.argmax(y_pred, dimension=1)
    এখন পর্যন্ত আমরা কি করলাম? ইনপুট ইমেজ নেয়ার ব্যবস্থা করেছি। সেই ইনপুট ইমেজগুলোর ট্রু ক্লাস ইনপুটের ব্যবস্থা করেছি। ইনপুট লেয়ার আর আউটপুট লেয়ার এর কাঠামো ঠিক করেছি। ইনপুট লেয়ার থেকে শূন্য ওয়েট গুন করে তারপর বায়াস যোগ করে আউটপুট লেয়ারে logits ম্যাট্রিক্স পেয়েছি এবং এটার উপর softmax, argmax আপ্লাই করে প্রত্যেকটি ইমেজের জন্য একটি করে ক্যালকুলেটেড ক্লাস পেয়েছি। অর্থাৎ ইনপুট নিয়ে মডেলের হিসাব করা রেজাল্ট পাওয়ার ব্যবস্থা হয়েছে। এরপর দেখতে হবে এই রেজাল্ট সঠিক ক্লাস থেকে কেমন ফারাকে আছে। তার উপর ভিত্তি করেই ওয়েট, বায়াস গুলো অ্যাডজাস্ট করবো।

    Cost ফাংশন ও অপটিমাইজেশন

    মডেলকে এফিসিয়েন্ট করার জন্য আমাদেরকে weights, biases এগুলা ওপ্টিমাইজ করতে হবে। আর এগুলো অপ্টিমাইজ করার জন্য আমাদেরকে জানতে হবে মডেলটা কত ভালো পারফর্ম করল। এটা বের করতে পারবো y_pred এবং y_true এর তুলনা করে। এই তুলনা করার অনেক রকম পদ্ধতির মধ্যে একটি পদ্ধতি হচ্ছে cross-entropy মিজারমেন্ট। ক্লাসিফিকেশন সমস্যার জন্য এটি একটি বহুল ব্যবহৃত Cost Function. এটি একটি Continuous Function যার মান সবসময় পজিটিভ। কিন্তু যদি প্রেডিক্টেড আউটপুট এবং আমাদের চাহিদা মোতাবেক আউটপুট একদম মিলে যায় তাহলে এর মান আসে শূন্য। তার মানে, আমরা যদি এই ফ্যাক্টরটির দিকে নজর রাখি এবং সব সময় চাই যে, ওয়েট - বায়াস অ্যাডজাস্ট করে করে এই ফ্যাক্টরটির মান যতটা শূন্যের কাছাকাছি আনা যায় -তাহলেই আমরা ভালো Accuracy এর দিকে আগাবো। খুশির খবর হচ্ছে TensorFlow এর একটা বিল্ট ইন ফাংশন আছে এই ক্রস-এন্ট্রপি বের করার জন্য। মনে রাখতে হবে, এই ফাংশনটি logits ম্যাট্রিক্স নিয়ে কাজ করে। কারন এটি নিজেই softmax এর কাজটা ভিতরে করে ফেলে। তাই y_pred = tf.nn.softmax(logits) লাইনের আগের ভ্যালু আমাদের এখানে দরকার।
    # Cell 18
    cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_true)
    যেহেতু আমরা একবারে পুরো logits ম্যাট্রিক্সকে ইনপুট হিসেবে দিয়েছি, তাই এই ম্যাট্রিক্সে যতগুলো ইমেজের ক্লাসিফিকেশন থাকবে সবগুলোর ক্রস-এন্ট্রপি বের করে ফেলছি উপরের লাইনে। তার মানে প্রত্যেকটি ইমেজের জন্যই আলাদা আলাদা ক্রস-এন্ট্রপি ভ্যালু পাবো আমরা। কিন্তু, পুরো সিস্টেমের অপটিমাইজেশন গাইড করার জন্য আমাদের একটা সিঙ্গেল ভ্যালু হলেই বরং ভালো। আর তাই, আমরা সাধারণ গড় করে নিতে পারি ওই আলাদা আলাদা ইমেজের আলাদা আলাদা ক্রস-এন্ট্রপি ভ্যালু গুলোর।
    # Cell 19
    cost = tf.reduce_mean(cross_entropy)
    অপটিমাইজেশন মেথডঃ
    তো, এখন যেহেতু আমাদের হাতে একটি Cost Measure থাকলো যেটাকে মিনিমাইজ করতে হবে, তাই এখন আমরা একটি অপ্টিমাইজার তৈরি করতে পারি। এই টিউটোরিয়ালে আমরা একটি ব্যাসিক অপ্টিমাইজার (Gradient Descent) ব্যবহার করবো। এটাও বিল্ট ইন আছে TensorFlow তে। আলাদা করে এটা বুঝতে এখানে ক্লিক করতে পারেন।

    # Cell 20
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.5).minimize(cost)
    এখানে 0.5 হচ্ছে গ্র্যাডিয়েন্ট খোজার স্টেপ সাইজ (যদি উপরের লিঙ্কে ক্লিক করে ঘুরে এসে থাকেন তাহলে এটা বুঝে ফেলার কথা)।
    এখানে খুব গুরুত্বপূর্ণ একটা কথা মনে রাখা জরুরি - উপরের স্টেটমেন্ট এক্সিকিউট করার সাথে সাথেই কিন্তু অপটিমাইজেশন শুরু হয়ে যায় নি। TensorFlow গ্রাফে আমরা একটা নতুন অবজেক্ট যুক্ত করেছি মাত্র। আসলে কোন কিছুই হয়নি এখন পর্যন্ত। পুরো গ্রাফকে রান করালে এসব কাজ করা শুরু করবে একসাথে। যেহেতু আমরা জুপিটার নোটবুকে এই সেল/কোডব্লক গুলো এক্সিকিউট করছি তাই এগুলো রানটাইম মেমোরিতে থাকছে মাত্র।
    পারফর্মেন্স মিজার করাঃ
    ঘটনা যাই হোক, আমাদের একটা ফ্যাক্টর রেডি করা উচিৎ যার দিকে তাকিয়ে আমরা এক কথায় বলে দিতে পারবো আমাদের মডেলের পারফর্মেন্স কেমন। অর্থাৎ যদি মডেল তৈরি করে ট্রেইন করার শেষে আমরা একটা একটা করে টেস্ট ইমেজ ইনপুট দিয়ে আউটপুট জেনে খাতায় টালি করে করে হিসাব রাখতে চাই যে - কয়টা ভুল হল আর কয়টা ঠিক হল; তাহলে খবর আছে। বরং আমরা কুইক হিসাব করে বের করতে চাই আসলে ওভারঅল পারফর্মেন্স কেমন। যাতে করে আমরা মডেলের রিডিজাইন এবং মডিফিকেশনে দ্রুত মন দিতে পারি। ফাইনালি যখন মডেলটি পাবলিক ইউজের জন্য ছেড়ে দেয়া হবে, তখন সেখানে ইউজার একটা করে ইনপুট দিয়ে দেখবে কাজ করছে কিনা।

    আমরা প্রথমে একটা বুলিয়ান ভেক্টর পেতে পারি নিচের মত করে,
    # Cell 21
    correct_prediction = tf.equal(y_pred_cls, y_true_cls)
    যার মধ্যে আছে প্রেডিক্টেড ক্লাস এবং ট্রু ক্লাসের মিল চেক করে জমা করা কিছু ট্রু, ফলস :) এরপর নিচের লাইনে আমরা সেই ভেক্টরটিকে আবার কাস্টিং করে ফ্লট এ কনভার্ট করছি যাতে করে ট্রু মানে 1 এবং ফলস মানে 0 হয়। আর শেষ নাগাদ এগুলোর গড় বের করলেই কিন্তু বোঝা যাচ্ছে যে টোটাল Accuracy কেমন। তাই না? সব যদি ট্রু হয় তাহলে ভেক্টরে থাকছে [1, 1, 1, 1, 1] (ধরি ৫টা ইমেজের ক্ষেত্রে) তাহলে গড় (যোগ দিয়ে ৫ দিয়ে ভাগ) তো 100% নাকি?
    # Cell 22
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    TensorFlow রান

    অনেক হয়েছে গ্রাফ সাজানো। এবার পুরো গ্রাফকে রান করার পালা আর এর ম্যাজিক দেখার পালা। তাহলে সেশন তৈরি করে ফেলিঃ
    # Cell 23
    session = tf.Session()
    ভ্যারিয়েবল গুলোকে ইনিসিয়ালিয়াজ করে ফেলি,
    # Cell 24
    session.run(tf.global_variables_initializer())
    কম রিসোর্সে অপটিমাইজেশন ফাংশনঃ
    আমার জেনেছি যে - আমাদের ডাটাসেটে ৫০,০০০ ট্রেনিং ইমেজ আছে। যদি এই পুরো ডাটাসেটকে একবারেই আমাদের অপ্টিমাইজার ফাংশনের উপর দিয়ে দেই তাহলে কম্পিউটেশনে প্রচুর সময় লাগবে (যদি না GPU বা হাই পাওয়ার CPU বা মেশিন হয়) তাই আমরা যেটা করতে পারি, প্রত্যেকবার কিছু কিছু ইমেজ নিয়ে এর মধ্যে দিতে পারি। যেমন একবারে ১০০ করে দিতে পারি। এখানে ১০০ কে বলা হয় একটা batch.

    # Cell 25
    batch_size = 100
    এই কাজ করার জন্য আমরা একটা হেল্পার ফাংশন তৈরি করে নেই নিচে,
    # Cell 26
    def optimize(num_iterations):
    for i in range(num_iterations):
    # Get a batch of training examples.
    # x_batch now holds a batch of images and
    # y_true_batch are the true labels for those images.
    x_batch, y_true_batch = data.train.next_batch(batch_size)
    # Put the batch into a dict with the proper names
    # for placeholder variables in the TensorFlow graph. # Note that the placeholder for y_true_cls is not set # because it is not used during training.
    feed_dict_train = {x: x_batch,
    y_true: y_true_batch}
    # Run the optimizer using this batch of training data.
    # TensorFlow assigns the variables in feed_dict_train
    # to the placeholder variables and then runs the optimizer.
    session.run(optimizer, feed_dict=feed_dict_train)
    ভয়ের কি আছে? ফাংশনটা আসলে ৪ লাইনের :) শুধু খেয়াল করার বিষয় হচ্ছে feed_dict_train ভ্যারিয়েবলটা। এটার মাধ্যমেই কিন্তু প্লেসহোল্ডারের মধ্যে সত্যিকারের ইনপুট দেয়া হচ্ছে। এক্ষেত্রে x আর y_true কিন্তু আমরাই ডিক্লেয়ার করেছিলাম প্লেসহোল্ডার হিসেবে। আরেকটা হেল্পার ফাংশন আমারা বানিয়ে নিতে পারি পারফর্মেন্স শো করার জন্য. এটার ক্ষেত্রে ফিড ডিকশনারি হবে টেস্ট ইমেজ গুলো নিয়ে। নিচের মত,
    # Cell 27
    feed_dict_test = {x: data.test.images, y_true: data.test.labels,
    y_true_cls: data.test.cls}
    আর ফাংশনটি হবে,
    # Cell 28
    def print_accuracy():
    # Use TensorFlow to compute the accuracy.
    acc = session.run(accuracy, feed_dict=feed_dict_test)
    # Print the accuracy.
    print("Accuracy on test-set: {0:.1%}".format(acc))
    ওয়েট ভিজুয়ালাইজ করাঃ
    এই পার্টটি অপশনাল। যদি কেউ দেখতে চান ওয়েট ম্যাট্রিক্স গুলো দেখতে কেমন হচ্ছে তাহলে নিচের হেল্পার ফাংশন ব্যবহার করা যেতে পারে। ওয়েট ম্যাট্রিক্স যেহেতু একটা ম্যাট্রিক্স আর আমি ম্যাট্রিক্স মানেই মনে করি ইমেজ তাই এটাও দেখতে ইমেজের মত হবে। হোক না দুই কালার ওয়ালা।

    # Cell 29
    def plot_weights():
    # Get the values for the weights from the TensorFlow variable. w = session.run(weights)
    # Get the lowest and highest values for the weights. # This is used to correct the colour intensity across # the images so they can be compared with each other. w_min = np.min(w)
    w_max = np.max(w)
    # Create figure with 3x4 sub-plots,
    # where the last 2 sub-plots are unused. fig, axes = plt.subplots(3, 4) fig.subplots_adjust(hspace=0.3, wspace=0.3)
    for i, ax in enumerate(axes.flat):
    # Only use the weights for the first 10 sub-plots.
    if i<10:
    # Get the weights for the i'th digit and reshape it. # Note that w.shape == (img_size_flat, 10)
    image = w[:, i].reshape(img_shape)
    # Set the label for the sub-plot.
    ax.set_xlabel("Weights: {0}".format(i))
    # Plot the image.
    ax.imshow(image, vmin=w_min, vmax=w_max, cmap='seismic')
    # Remove ticks from each sub-plot.
    ax.set_xticks([])
    ax.set_yticks([])
    পরের টিউটোরিয়ালে কনভলিউশন বোঝার জন্য ওয়েট ম্যাট্রিক্স এর ভিজুয়ালাইজেশন বোঝা উপকারী।
    কোন রকম অপ্টিমাজেশনের আগেই পারফর্মেন্স চেক করিঃ
    আমরা যদি এই অবস্থায় নোটবুকের নতুন একটি সেলে নিচের কোড এক্সিকিউট করে accuracy দেখতে চাই,

    # Cell 30
    print_accuracy()
    তাহলে আউটপুট আসবে,
    Accuracy on test-set: 9.8%
    কারন কি? মডেল ট্রেনিং করার আগেই কিভাবে শতকরা 10 ভাগ সঠিক উত্তর দেয়া শুরু করলো? আজব না? কারন হচ্ছে - আমাদের ওয়েট বায়াস শূন্য। তাই মডেল সব ইমেজকে প্রেডিক্ট করে শূন্য হিসেবে। কাকতালীয় ভাবে টেস্ট ইমেজ গুলোর মধ্যে শতকরা ১০ ভাগের মত ইমেজ ছিল শূন্যের। তাই সেগুলোর ক্ষেত্রে যখন প্রেডিক্টেড আর ট্রু ক্লাস মিলে গেছে, তাই accuracy আসতেছে 10% এর মত।
    ঝড়ে বক মরে ফকিরের কেরামতি বারে
    অপটিমাইজেশন শুরু করিঃ
    আমি এই পোস্টের শুরুর দিকের একটা উদাহরনেও একটা লুপকে ১টা সাইকেলে আটকে রেখে ভ্যালু গুলো নিয়ে যাচাই বাছাই এর কথা বলেছিলাম। এবারও সেরকম একটা এক্সপেরিমেন্ট করা যায়। আমরা একটি মাত্র অপটিমাইজেশন ইটারেশন করবো শুরুতে।

    # Cell 31
    optimize(num_iterations=1)
    # Cell 32
    print_accuracy()
    Accuracy on test-set: 40.7%
    একটা ইটারেশনেই প্রায় ৪০% সঠিক রেজাল্ট দিতে শিখেছে এই মডেল। বলে নেয়া ভালো - একটা ইটারেশনে কিন্তু এক ব্যাচ পরিমাণ ইমেজ নিয়ে কাজ করে মডেলটি। প্রত্যেক ইটারেশনে নতুন এবং পরবর্তী ব্যাচ (১০০টি) নিয়ে কাজ করে। optimize ফাংশনের কোড খেয়াল করুন। তো, এ অবস্থায় ওয়েট গুলো দেখতে চাইলে,
    # Cell 33
    plot_weights()
    আউটপুট আসবে নিচের মত,
    এখানে বলে নেয়া ভালো পজিটিভ ওয়েট গুলোকে লাল রং এবং নেগেটিভ ওয়েট গুলোকে নীল রং -এ প্রকাশ করা হয়েছে। মনে আছে অনেক আগের সেকশনে আমরা এরকম ওয়েট ম্যাট্রিক্স দিয়ে কনভলিউশনের ব্যাসিক ধারনা নিয়েছিলাম? যেখানে ম্যাট্রিক্স গুলো দেখতে ছিল [[+ -], [- +]] এরকম? এগুলোকেই ফিল্টার হিসাবে বলা হবে কনভলিউশন লেয়ারে। এখানে আমাদের মডেল ট্রেনিং করে শিখে এরকম ওয়েট ম্যাট্রিক্স ধরে নিয়েছে এবং দেখেছে যে এরকম ওয়েট ম্যাট্রিক্স হলে সেই রিলেটেড ফটো গুলোর সাথে রিয়েকশন পজিটিভ হয়। অর্থাৎ, যদি একটা 0 ওয়ালা ইমেজের সাথে এই ফিল্টারের দেখা হয় (এক্ষেত্রে ডাইরেক্ট x*W. কোন নির্দিষ্ট পার্টের সাথে কনভলিউশন নয়) তাহলে এই ফিল্টার সেই ফটোর সাথেই পজিটিভ রিয়েকশন করবে যার মধ্যে একটি সার্কেল টাইপ দাগ আছে। আর সেগুলোর সাথে নেগেটিভ রিয়েকশন করবে যেগুলোর মাঝখানটায় এক গাদা কালি আছে। তার মানে সে শূন্য লেখা আছে এমন ফটোর সাথে বেশি পজিটিভ ভ্যালু তৈরি করবে। এসব আরও বিস্তারিত বোঝা যাবে যাবে পরের টিউটোরিয়ালে যেখানে কনভলিউশনাল নিউরাল নেটওয়ার্ক ডিজাইন করা হবে এই মডেলকেই আরও ইফিসিয়েন্ট করার জন্য।
    যা হোক, এবার ১০০০ অপটিমাইজেশন ইটারেশন করে দেখা যাকঃ
    # Cell 34
    # We have already performed 1 iteration already.
    optimize(num_iterations=999)
    # Cell 35
    print_accuracy()
    Accuracy on test-set: 91.7%
    খেয়াল করুন, শুধুমাত্র লিনিয়ার মডেল ডিজাইন করেও ৯১% Accuracy পাওয়া গেছে। এটা সম্ভব হয়েছে ডিপ লার্নিং এর কারনেই। এখানে আমরা ইমেজ থেকে ফিচার এক্সট্র্যাক্ট করে দেই নি। শুধু ডাইরেক্ট পিক্সেল ভ্যালু গুলোকে ইনপুট লেয়ারে দিয়ে আউটপুট লেয়ারে ট্রু ক্লাস দিয়ে ট্রেনিং করে মডেল ভ্যারিয়েবল গুলোকে অ্যাডজাস্ট করতে বলেছি। এতেই সে ওয়েট ম্যাট্রিক্স ধারনা করা শিখে গেছে। চাইলে এই অবস্থাতেও ওয়েট গুলো ভিজুয়ালাইজ করে দেখতে পারেন আর কোন প্রশ্ন থাকলে করতে পারেন।
    # Cell 36
    plot_weights()
    এখানে দেখা যাচ্ছে ওয়েট ম্যাট্রিক্স গুলো আরও একটু জটিল হিসাবে মগ্ন। অর্থাৎ এমন না যে সার্কেল ধরে পজিটিভ ওয়েট সেট করেছে (যেমন 0 এর ক্ষেত্রে)। বরং একটু ছাড়া ছাড়া ভাবে। এটা সে করতে বাধ্য হয়েছে এক এক জনের এক এক রকম শূন্য লেখার সঙ্গে নিজেকে মানিয়ে নিতে গিয়ে।
    অনেক হল গবেষণা। তো, এবার আমরা TensorFlow এর সেশন ক্লোজ করতে পারি নিচের মত।
    # Cell 37
    session.close()
    উপরের আলোচ্য ধাপ গুলো নিয়ে পূর্ণ .ipynb ডকুমেন্টটি পাওয়া যাবে এখানে
    পূর্ণ প্রোগ্রামঃ যারা নোটবুকে ধাপে ধাপে এই কোড ব্লক গুলো এক্সিকিউট করেছেন বোঝার জন্য এবং এখন গোছানো একটা প্রোগ্রাম চান যেকোনো জায়গায় রান করার জন্য - ক্লিক করুন এখানে

    TensorFlow দিয়ে কনভলিউশনাল NN

    This page is empty.






  • 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