<h2 id=A/B Testing> A/B Testing</h2><div class="visible-content"> #Article #RecommenderSystems #NeuralNetwork #Embeddings #EfficiencyImprovement #AWS #MLOps #Blog #TwoTowerModel


Issue Date: 2025-06-29 日経電子版のアプリトップ「おすすめ」をTwo Towerモデルでリプレースしました, NIKKEI, 2025.05 Comment<p>リアルタイム推薦をするユースケースにおいて、ルールベース+協調フィルタリング(Jubatus)からTwo Towerモデルに切り替えた際にレイテンシが300ms増えてしまったため、ボトルネックを特定し一部をパッチ処理にしつつもリアルタイム性を残すことで解決したという話。AWSの構成、A/Bテストや負荷テストの話もあり、実用的で非常に興味深かった。</p>

#Article #RecommenderSystems #NeuralNetwork #CTRPrediction #NewsRecommendation #MLOps #Evaluation #Blog


Issue Date: 2024-08-31 NewsPicksに推薦システムを本番投入する上で一番優先すべきだったこと, 2024.08 Comment<p>>推薦モデルの良し悪しをより高い確度で評価できる実験を、より簡単に実行できる状態を作ることでした。平たく言えば「いかにA/Bテストしやすい推薦システムを設計するか」が最も重要だった訳です。

オフライン評価とオンライン評価の相関がない系の話で、A/Bテストを容易に実施できる環境になかった、かつCTRが実際に向上したモデルがオフライン評価での性能が現行モデルよりも悪く、意思決定がなかなかできなかった、という話。

うーんやはり、推薦におけるオフライン評価ってあまりあてにできないよね、、、
そもそも新たなモデルをデプロイした時点で、テストした時とデータの分布が変わるわけだし、、、

Off-Policy Evaluationの話は勉強したい。</p><p>あと、定性評価は重要</p>


#Article #Blog


Issue Date: 2023-04-26 Controlled experiments on the web: survey and practical guide, 2023 Comment<p>A/Bテストのベストプラクティスが書かれているらしい</p>

</div>

if ('IntersectionObserver' in window) {
  const observer = new IntersectionObserver((entries, obs) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const el = entry.target;
        const html = el.getAttribute('data-embed');
        if (html) {
          const placeholder = el.querySelector('.tweet-placeholder');
          if (placeholder) placeholder.remove();

          el.innerHTML = html.trim();

          if (window.twttr?.widgets?.load) {
            window.twttr.widgets.load(el);
          }
        }
        obs.unobserve(el); // 処理済みは監視解除
      }
    });
  }, {
    rootMargin: '500px 0px', // 画面手前200pxで読み込み開始
    threshold: 0
  });

  tweets.forEach(tweet => observer.observe(tweet));

} else {
  // IntersectionObserver未対応ブラウザ用のフォールバック
  function lazyLoadFallback() {
    tweets.forEach(el => {
      if (el.getAttribute('data-embed') && el.getBoundingClientRect().top < window.innerHeight) {
        const html = el.getAttribute('data-embed');
        const loadingImg = el.querySelector('.tweet-loading');
        if (loadingImg) loadingImg.remove();
        el.innerHTML = html.trim();
        el.removeAttribute('data-embed');
        if (window.twttr?.widgets?.load) {
          window.twttr.widgets.load(el);
        }
      }
    });
  }
  window.addEventListener('scroll', lazyLoadFallback);
  lazyLoadFallback();
}   }); </script>