Search on the blog

2018年5月13日日曜日

español 21

Hola. ¿cómo estás?

esta, este, estoなどの違いがよくわからなかったのでまとめてみた。

Thisに対応するもの
esto = これ
este = この(男性名詞につける)
esta = この(女性名詞につける)
estos = esto, esteの複数形
estas = estaの複数形

Thatに対応するもの
eso = あれ
ese = あの(男性名詞につける)
esa = あの(女性名詞につける)
esos = eso, eseの複数形
esas = esaの複数形

例文
Esto es tu regalo de cumpleaños.
これはあなたの誕生日プレゼントです。
- regalo = present 
- cumpleaños = birthday

Este libro es mía.
この本は私のものです。
- libro = book
- mía = mine

Me encanta esta canción.
私はこの歌がすきです。
- encanta (encantar) = love
- canción = song

¿Puedes ver esa pequeña casa?
あの小さな家が見えますか?
- puedes (ponder) = to be able to
- pequeño = small
- ver = to see

Yo soy una de esas personas.
私はあの人たちの一員です。

¡Quiero eso!
あれが欲しい!
- quiero(querer) = want

español 20

¡Hola, buenas noches!

今日は前回の続きでレストランで使える表現を勉強した。

Soy vegetariano.
私はベジタリアンです。

No como carne.
肉は食べません。

No como marisco.
シーフードは食べません。

Soy alérgico a los productos lácteos.
私は、乳製品アレルギーです。

Esto está demasiado frío.
これは冷たすぎます。
- esto = this
- está (conjugated form of "estar")  = is
- demasiado = too
- frío = cold

Esto está demasiado caliente.
これは熱すぎます。
- caliente = hot

Esto está quemado.
これは焦げています。
- quemado = burnt

Esto está demasiado picante. Nos trae más agua, por favor.
これは辛すぎます。水をもってきてください。
- picante = spicy

Esto está buenísimo.
これはとても美味しいです。
- buenísimo = really good

¿Quieres más?
もっと欲しいですか?

No gracias. Estoy satisfecho.
結構です。満腹です。
- satisfecho = satisfied, full


2018年4月28日土曜日

español 19

¡Hola, amigo!
Me llamo Kenji. Estoy aprendiendo español.

今日は、mi amigaとレストランに行くことを想像しつつ、レストランでの会話の練習をした。

Tengo hambre.
お腹すいたよ。
- tengo = (I) have

Tengo sed. ¿Tienes algo de tomar?
喉が乾いた。何か飲み物もってる?
- algo = something
- tomar = drink

¿Tiene una mesa para dos?
二人ですが、テーブル空いてますか?
- mesa = table

¿Fumadores o no fumadores?
喫煙席ですか?禁煙席ですか?
- o = or

Lo siento. Hemos cerrado.
ごめんなさい。閉店しています。
- hemos = (we) have
- cerrado = closed

Estamos llenos. Hay que esperar.
満席です。待たないといけません。
- llenos = full
- hay que = one must
- esperar = wait

¿Cuánto hay que esperar?
どれくらい待たないといけませんか?
- cuánto = how long

¿Tiene un menú en inglés?
英語のメニューはありますか?

Quiero esto.
これください。
- quiero = (I) want
- esto = this

¿Qué me recomienda?
何がオススメですか?
- qué = what

¿Que están comiendo ellos?
彼らは何を食べているのですか?

¿Qué lleva este plato?
この料理には何が入っていますか?
- lleva = (it) carries
- este = this
- plato = dish


2018年4月21日土曜日

A Survey on Real Time Bidding Advertising

元ネタ
A Survey on Real Time Bidding Advertising

気付き
- DSPはSSPから広告枠を買い付けていると思っていたが、厳密にはAd Exchangeから買っているらしい。SSPと思っていたサービスのサイトをよく見ると、確かにAd Exchangeと書いていた。

- 広告主からマージンをもらって儲けるOpen DSPと、自社の様々な事業の広告を配信して事業の売り上げ増加を目指すNative DSPでは戦略が違うので、その辺りを意識してサーベイする必要がある。

メモ
RTB広告の成長
- 2017年にはディスプレイ広告予算の29%を占める見込み
- 昔: プレミアムな在庫はオフラインで、残りはRTBで
- 最近: プレミアムな在庫もRTBで

DSPでは効率的な入札アルゴリズムが重要
- 最適な広告を選択する
- 最適な入札額を決める

DSPが目指すパフォーマンスの最大化
- インプレッション数
- クリック数
- コンバージョン数

DSPの時間制約
- 10〜100 milli sec
- 入札戦略を最適化するオフラインコンポーネント
- 前もって最適化された戦略を実行するオンラインコンポーネント

予算配分
- 複数の媒体
- DSP業者
- キャンペーン

オークション方式
- Vickery (セカンドプライス)
- OSP (オプショナルセカンドプライス)

フリークエンシーキャップの最適化
- RTBでは個々のクッキーに対してフリークエンシーを制御できる
- 広告主の予算の浪費を抑える

2018年4月19日木曜日

Apache Beam: 正常データ、異常データを別々に処理

 Beam 1.xのときは、side outputを使って異常系のデータをDLQに別途出力するということができた。Beam 2.xになってからside outputがなくなっていたので、どうやるかを試してみた。以下のようにPTransformの中でタグをつけて出力すれば良さそう。

 今回はDLQとしてキューじゃないけどGCSを使ってみた。UnboundedなデータをBoundedな場所に格納することになるのでややこしそうだけど、windowを使えば簡単に実現できる。

サンプルコード

package com.kenjih.sample.side_output;

import org.apache.beam.runners.dataflow.options.DataflowPipelineOptions;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.io.TextIO;
import org.apache.beam.sdk.io.gcp.pubsub.PubsubIO;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.transforms.windowing.FixedWindows;
import org.apache.beam.sdk.transforms.windowing.Window;
import org.apache.beam.sdk.values.PCollection;
import org.apache.beam.sdk.values.PCollectionTuple;
import org.apache.beam.sdk.values.TupleTag;
import org.apache.beam.sdk.values.TupleTagList;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * GCS-based Dead letter queue example
 *
 * @see <a href="https://stackoverflow.com/questions/45173668/gcp-dataflow-2-0-pubsub-to-gcs/45256314#45256314">GCP Dataflow 2.0 PubSub to GCS</a>
 * @see <a href="https://cloud.google.com/blog/big-data/2016/01/handling-invalid-inputs-in-dataflow">Handling Invalid Inputs in Dataflow</a>
 */
public class Main {

  private static final Logger LOG = LoggerFactory.getLogger(Main.class);

  private static class ParseToIntDoFn extends DoFn<String, String> {

    private final TupleTag<String> successTag;
    private final TupleTag<String> invalidTag;

    public ParseToIntDoFn(TupleTag<String> successTag, TupleTag<String> invalidTag) {
      this.successTag = successTag;
      this.invalidTag = invalidTag;
    }

    @ProcessElement
    public void processElement(ProcessContext c) {
      String s = c.element();
      try {
        Integer i = Integer.parseInt(s);
        c.output(successTag, i.toString());
      } catch (Exception e) {
        LOG.error("cannot convert {} to an integer", s);
        c.output(invalidTag, s);
      }
    }
  }

  private static String createTopicPath(String projectId, String topicName) {
    return String.format("projects/%s/topics/%s", projectId, topicName);
  }

  public static void main(String[] args) {
    LOG.info("begin the application");

    DataflowPipelineOptions options = PipelineOptionsFactory.fromArgs(args).withValidation()
        .as(DataflowPipelineOptions.class);
    options.setStreaming(true);

    Pipeline pipeline = Pipeline.create(options);
    String projectId = options.getProject();

    final TupleTag<String> successTag = new TupleTag<String>() {};
    final TupleTag<String> invalidTag = new TupleTag<String>() {};

    PCollection<String> input =
        pipeline.apply("read",
            PubsubIO.readStrings().fromTopic(createTopicPath(projectId, "kh-test-in-1")));

    PCollectionTuple outputTuple =
        input.apply("parse", ParDo.of(new ParseToIntDoFn(successTag, invalidTag))
            .withOutputTags(successTag, TupleTagList.of(invalidTag)));

    // write successful data to PubSub
    PCollection<String> success = outputTuple.get(successTag);
    success
        .apply("success-write", PubsubIO.writeStrings()
            .to(createTopicPath(projectId, "kh-test-out-1")));

    // write invalid data to GCS
    PCollection<String> invalid = outputTuple.get(invalidTag);
    invalid
        .apply("windowing", Window.into(FixedWindows.of(Duration.standardMinutes(1))))
        .apply("invalid-write", TextIO.write()
            .to("gs://kh-test/dead-letter/")
            .withNumShards(3)
            .withWindowedWrites());

    pipeline.run();

    LOG.info("end the application");
  }


}

Dataflow Runnerでの実行した結果

2018年4月18日水曜日

español 18

¡Hola a todos!


今日はバールに行って注文する表現を勉強しました。
よく使いそうな単語には個別でメモをつけるようにしました。

Qué van a tomar?
注文は何にしましょうか?
  - qué = what
  - van (3rd person plural of "ir") = go
  - a = to
  - tomar = to take, to drink

Un café con leche, por favor.
ミルクコーヒーをください。

Para mí un té con limón y para mi amigo una limonada.
私はレモンティーで、友達にはレモネードをください。
  - para = for
  - con = with

Quiero un vino tinto (blanco).
赤(白)ワインが欲しいです。
 - quiero (1st person singular of "querer") = want, love

Otro zumo de naranja, por favor.
オレンジジュースをもう一つください。
  - otro = another

Otra Coca Cola, por favor.
コカコーラをもう一つください。
  - otra = otroの女性形

¿Se puede comer aqui?
ここで食べれますか?
  - puede (3rd person singular of "poder") = can

Nos (Me) trae la carta, por favor.
私たちに(私に)メニューを持ってきてください。

Quieren algo más?
他にも注文はありますか?
  - algo = something
  - más = more 

Nos trae más agua con (sin) gas, por favor.
炭酸の入っている(いない)水をもっとください。
  - con = with
  - sin = without

Nos trae la cuenta, por favor.
お会計お願いします。

Gracias y hasta pronto.

2018年4月17日火曜日

Apache Beam: 複数のパイプラインをあげる

 Apache Beamで構築するグラフはDAGじゃないといけないという縛りがありますが、DAGであれば連結なグラフじゃなくてもいいらしいです。(これに気づかなくて数ヶ月悩んでました。)
 
 実際にそのようなサンプルを書いて動作確認してみました。

package com.kenjih.multiple_pipe_line;

import org.apache.beam.runners.dataflow.options.DataflowPipelineOptions;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.io.gcp.pubsub.PubsubIO;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.ParDo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {

  private static final Logger LOG = LoggerFactory.getLogger(Main.class);

  private static class AddPrefixDoFn extends DoFn<String, String> {

    private final String prefix;

    private AddPrefixDoFn(String prefix) {
      this.prefix = prefix;
    }

    @ProcessElement
    public void processElement(ProcessContext context) {
      String element = context.element();
      context.output(prefix + element);
    }
  }

  private String createTopicPath(String projectId, String topicName) {
    return String.format("projects/%s/topics/%s",
        projectId,
        topicName);
  }

  public void run(DataflowPipelineOptions options) {
    Pipeline pipeline = Pipeline.create(options);
    String projectId = options.getProject();

    // a data pipeline
    pipeline
        .apply("read-1",
            PubsubIO.readStrings().fromTopic(createTopicPath(projectId, "kh-test-in-1")))
        .apply("transform-1",
            ParDo.of(new AddPrefixDoFn("transform-1: ")))
        .apply("write-1",
            PubsubIO.writeStrings().to(createTopicPath(projectId, "kh-test-out-1")));

    // another data pipeline
    pipeline
        .apply("read-2",
            PubsubIO.readStrings().fromTopic(createTopicPath(projectId, "kh-test-in-2")))
        .apply("transform-2",
            ParDo.of(new AddPrefixDoFn("transform-2: ")))
        .apply("write-2",
            PubsubIO.writeStrings().to(createTopicPath(projectId, "kh-test-out-2")));

    // yet another data pipeline
    pipeline
        .apply("read-3",
            PubsubIO.readStrings().fromTopic(createTopicPath(projectId, "kh-test-in-3")))
        .apply("transform-3",
            ParDo.of(new AddPrefixDoFn("transform-3: ")))
        .apply("write-3",
            PubsubIO.writeStrings().to(createTopicPath(projectId, "kh-test-out-3")));

    pipeline.run();
  }

  public static void main(String[] args) {
    LOG.info("begin the application");

    DataflowPipelineOptions options = PipelineOptionsFactory.fromArgs(args).withValidation()
        .as(DataflowPipelineOptions.class);
    options.setStreaming(true);

    new Main().run(options);

    LOG.info("end the application");
  }

}

GCPのコンソール画面で見ると以下のようになっています。
BigQueryIOのDynamicDestinationsのようなものがPubSubIOにはなくて困っていましたが、上のように独立したパイプラインを作ることができるので、それを応用することでDynamicDestinations的なことができそうです(パイプライン生成時に静的に決めないといけないのでDynamicとは違いますが、複数の可変的な汎用パイプラインをうまく扱えそうという意味です)。