স্পার্কের ALS সুপারিশ অ্যালগরিদম PlatoBlockchain ডেটা ইন্টেলিজেন্সে ড্রিলিং। উল্লম্ব অনুসন্ধান. আ.

স্পার্কের এএলএসের প্রস্তাবনা অ্যালগরিদমে ড্রিলিং

ALS অ্যালগরিদম দ্বারা প্রবর্তিত হু এট আল।, সুপারিশকারী সিস্টেম সমস্যায় ব্যবহৃত একটি খুব জনপ্রিয় কৌশল, বিশেষ করে যখন আমাদের অন্তর্নিহিত ডেটাসেট থাকে (উদাহরণস্বরূপ ক্লিক, পছন্দ ইত্যাদি)। এটি প্রচুর পরিমাণে ডেটা যুক্তিসঙ্গতভাবে পরিচালনা করতে পারে এবং আমরা বিভিন্ন মেশিন লার্নিং ফ্রেমওয়ার্কগুলিতে অনেক ভাল বাস্তবায়ন খুঁজে পেতে পারি। স্পার্ক MLlib কম্পোনেন্টে অ্যালগরিদম অন্তর্ভুক্ত করে যা সম্প্রতি পঠনযোগ্যতা এবং কোডের আর্কিটেকচার উন্নত করার জন্য রিফ্যাক্টর করা হয়েছে।

স্পার্কের বাস্তবায়নের জন্য আইটেম এবং ব্যবহারকারীর আইডিকে পূর্ণসংখ্যা পরিসরের মধ্যে সংখ্যা হতে হবে (হয় পূর্ণসংখ্যার ধরন বা পূর্ণসংখ্যার পরিসরের মধ্যে দীর্ঘ), যা যুক্তিসঙ্গত কারণ এটি ক্রিয়াকলাপের গতি বাড়াতে এবং মেমরি খরচ কমাতে সাহায্য করতে পারে। কোডটি পড়ার সময় আমি একটি জিনিস লক্ষ্য করেছি যে সেই আইডি কলামগুলি ফিট/পূর্বাভাস পদ্ধতির শুরুতে দ্বৈত এবং তারপর পূর্ণসংখ্যাগুলিতে কাস্ট করা হচ্ছে। এটি কিছুটা হ্যাকি বলে মনে হচ্ছে এবং আমি দেখেছি এটি আবর্জনা সংগ্রাহকের উপর অপ্রয়োজনীয় চাপ ফেলেছে। এখানে লাইন আছে ALS কোড যে আইডিগুলিকে দ্বিগুণ করে:
স্পার্কের ALS সুপারিশ অ্যালগরিদম PlatoBlockchain ডেটা ইন্টেলিজেন্সে ড্রিলিং। উল্লম্ব অনুসন্ধান. আ.
স্পার্কের ALS সুপারিশ অ্যালগরিদম PlatoBlockchain ডেটা ইন্টেলিজেন্সে ড্রিলিং। উল্লম্ব অনুসন্ধান. আ.

কেন এটি করা হয় তা বোঝার জন্য, একজনকে চেকডকাস্টটি পড়তে হবে:
স্পার্কের ALS সুপারিশ অ্যালগরিদম PlatoBlockchain ডেটা ইন্টেলিজেন্সে ড্রিলিং। উল্লম্ব অনুসন্ধান. আ.

এই UDF একটি ডাবল পায় এবং এর পরিসীমা পরীক্ষা করে এবং তারপরে এটিকে পূর্ণসংখ্যায় ফেলে। এই UDF স্কিমা বৈধতা জন্য ব্যবহার করা হয়. প্রশ্ন হল আমরা কুশ্রী ডাবল কাস্টিং ব্যবহার না করে এটি অর্জন করতে পারি? আমি হ্যাঁ বিশ্বাস:

  protected val checkedCast = udf { (n: Any) =>
    n match {
      case v: Int => v // Avoid unnecessary casting
      case v: Number =>
        val intV = v.intValue()
        // True for Byte/Short, Long within the Int range and Double/Float with no fractional part.
        if (v.doubleValue == intV) {
          intV
        }
        else {
          throw new IllegalArgumentException(s"ALS only supports values in Integer range " +
            s"for columns ${$(userCol)} and ${$(itemCol)}. Value $n was out of Integer range.")
        }
      case _ => throw new IllegalArgumentException(s"ALS only supports values in Integer range " +
        s"for columns ${$(userCol)} and ${$(itemCol)}. Value $n is not numeric.")
    }
  }

উপরের কোডটি একটি পরিবর্তিত চেকডকাস্ট() দেখায় যা ইনপুট গ্রহণ করে, চেক দাবি করে যে মানটি সংখ্যাসূচক এবং অন্যথায় ব্যতিক্রমগুলি উত্থাপন করে। যেহেতু ইনপুটটি যেকোন, তাই আমরা নিরাপদে কোডের বাকি অংশ থেকে সমস্ত কাস্ট টু ডাবল স্টেটমেন্ট সরিয়ে ফেলতে পারি। অধিকন্তু এটা আশা করা যুক্তিসঙ্গত যে যেহেতু ALS-এর জন্য পূর্ণসংখ্যা পরিসরের মধ্যে আইডি প্রয়োজন, তাই বেশিরভাগ মানুষ প্রকৃতপক্ষে পূর্ণসংখ্যার ধরন ব্যবহার করে। ফলস্বরূপ লাইন 3-এ এই পদ্ধতিটি পূর্ণসংখ্যাগুলিকে স্পষ্টভাবে পরিচালনা করে যাতে কোনও কাস্টিং করা না হয়। অন্যান্য সমস্ত সাংখ্যিক মানের জন্য এটি ইনপুটটি পূর্ণসংখ্যার সীমার মধ্যে আছে কিনা তা পরীক্ষা করে। এই চেক লাইন 7 এ ঘটে.

কেউ এটি ভিন্নভাবে লিখতে পারে এবং স্পষ্টভাবে সমস্ত অনুমোদিত প্রকারগুলি পরিচালনা করতে পারে। দুর্ভাগ্যবশত এটি ডুপ্লিকেট কোডের দিকে পরিচালিত করবে। পরিবর্তে আমি এখানে যা করি তা হল সংখ্যাটিকে পূর্ণসংখ্যাতে রূপান্তর করা এবং মূল সংখ্যার সাথে তুলনা করা। যদি মানগুলি অভিন্ন হয় তবে নিম্নলিখিতগুলির মধ্যে একটি সত্য:

  1. মান হল বাইট বা শর্ট।
  2. মানটি দীর্ঘ কিন্তু পূর্ণসংখ্যা পরিসরের মধ্যে।
  3. মানটি ডাবল বা ফ্লোট কিন্তু কোনো ভগ্নাংশ ছাড়াই।

কোডটি ভালভাবে চলে তা নিশ্চিত করার জন্য আমি এটিকে স্পার্কের স্ট্যান্ডার্ড ইউনিট-পরীক্ষার সাথে পরীক্ষা করেছি এবং বিভিন্ন আইনি এবং অবৈধ মানগুলির জন্য পদ্ধতির আচরণ পরীক্ষা করে ম্যানুয়ালি করেছি। সমাধানটি অন্তত মূলের মতো দ্রুত তা নিশ্চিত করতে, আমি নীচের স্নিপেটটি ব্যবহার করে বহুবার পরীক্ষা করেছি। এই স্থাপন করা যেতে পারে ALSSuite ক্লাস স্পার্ক এ:

  test("Speed difference") {
    val (training, test) =
      genExplicitTestData(numUsers = 200, numItems = 400, rank = 2, noiseStd = 0.01)

    val runs = 100
    var totalTime = 0.0
    println("Performing "+runs+" runs")
    for(i <- 0 until runs) {
      val t0 = System.currentTimeMillis
      testALS(training, test, maxIter = 1, rank = 2, regParam = 0.01, targetRMSE = 0.1)
      val secs = (System.currentTimeMillis - t0)/1000.0
      println("Run "+i+" executed in "+secs+"s")
      totalTime += secs
    }
    println("AVG Execution Time: "+(totalTime/runs)+"s")

  }

কয়েকটি পরীক্ষার পরে আমরা দেখতে পাচ্ছি যে নতুন ফিক্সটি আসলটির চেয়ে কিছুটা দ্রুত:

কোড

রানের সংখ্যা

মোট মৃত্যুদন্ডের সময়

রান প্রতি গড় এক্সিকিউশন সময়

মূল 100 588.458s 5.88458s
ফিক্সড 100 566.722s 5.66722s

আমি নিশ্চিত করার জন্য পরীক্ষাগুলি একাধিকবার পুনরাবৃত্তি করেছি এবং ফলাফলগুলি সামঞ্জস্যপূর্ণ। এখানে আপনি একটি পরীক্ষার জন্য বিস্তারিত আউটপুট খুঁজে পেতে পারেন মূল কোড এবং ঠিক করা. একটি ক্ষুদ্র ডেটাসেটের জন্য পার্থক্যটি ছোট কিন্তু অতীতে আমি এই ফিক্সটি ব্যবহার করে GC ওভারহেডে একটি লক্ষণীয় হ্রাস অর্জন করতে পেরেছি। আমরা স্থানীয়ভাবে স্পার্ক চালিয়ে এবং স্পার্ক ইনস্ট্যান্সে একটি জাভা প্রোফাইলার সংযুক্ত করে এটি নিশ্চিত করতে পারি। আমি একটি খোলা টিকিট এবং একটি টান-অনুরোধ অফিসিয়াল স্পার্ক রেপোতে কিন্তু এটা একত্রিত করা হবে কিনা তা অনিশ্চিত, আমি এখানে আপনার সাথে শেয়ার করার চিন্তা করেছি এবং এটি এখন স্পার্ক 2.2 এর অংশ।

কোন চিন্তা, মন্তব্য বা সমালোচনা স্বাগত জানাই! 🙂

সময় স্ট্যাম্প:

থেকে আরো ডেটাবক্স