타임라인 광고 타겟팅 – timeline ad targeting

 

지금 하는 일과 관련이 있는 것이라서 zdnet기사에 앱넥스트라는 회사에서 제안했다고 하는 타임라인 타겟팅이라는 기법(아이디어)에 대한 기사를 스크랩해 놓은적이 있는데 내용도 정리할겸 그림툴도 써볼겸(사실은 이게 본래의 포스팅 목적입니다 ‘ㅡ’;;) 해서 포스트를 올립니다.

직접 기사를 읽어보시면 되겠지만 저는 그림툴을 사용해 보는 것이 목적이므로 정리를 좀 해보자면 이렇습니다.

최근의 앱인스톨 광고 그러니까 앱인스톨을 유도하는 배너 광고들이 실적이 좋지 않다고 합니다.  그 이유 중의 하나가 이제 사람들은 자기 스마트폰에 더 이상 새로운 앱을 설치하지 않는다고 합니다.

  1. 이미 필요한 것을 대부분 설치했고 사용하는 것들이 몇개에 한정되어 있기 때문입니다.
  2. 그리고 필요한 것이 생기면 그때그때 찾아서 설치해도 되니 미리 설치해 둘 필요는 없습니다.
  3. 게임이 아니라면 그런 배너에 반응을 잘 안하게 되는 게임도 설치 광고가 그렇게 큰 효과를 보지 못한다는 말이 많습니다. (다 그런것은 아니겠지만요)

그래서 위 기사에서 말하는 아이디어는 이렇습니다.

일종의 개인화 타겟팅(personalized targeting)인데 위의 그림처럼 사람들의 타임라인을 추적(감시한다기 보다는 엿본다는 것이 맞겠습니다)해서 상황들을 모니터링하다가 특정 상황이 되면 그 상황에 필요한 앱인데 아직 사용자가 설치하지 않은 앱이 있다면 광고로 추천해서 바로 설치하도록 유도한다는 것입니다.

그러기 위해서 사용자가 사용하고 있는 스마트폰에 항상 사용자의 액션을 모니터링하는 앱이 필요한데 사실 대부분의 회사들이 이걸 하기가 현실적으로 불가능합니다. 스마트폰의 모든 상황을 전역으로 감시하는 장치를 스마트폰에 심을 수가 없기 때문입니다.

앱넥스트라는 회사는 자사의 SDK(스마트폰 애플리케이션에 광고를 노출할 수 있도록 해주는 킷)를 사용한 제휴 앱들을 이용해서 사용자의 행적(activity)를 보고 있다가 다른 앱을 설치하도록 유도할 수 있다는 것입니다. 알려주는 것은 아마 Push 기능 같은 것을 사용하지 않을까 싶습니다.

실현이 가능하다면 “앱을 설치할 수 밖에 없는 적절한 상황을 찾아서 그때 광고를 보여주면 설치를 많이 하겠지” 라는 것을 이용한 것인데요.

이걸 하기 위해서는 사실 앱 매체(광고를 보여주는 앱들)을 많이 제휴하고 있어서 그 앱들을 사용자가 늘 쓰고 있거나 빈번하게 쓰고 있어야 합니다. 즉 앱 매체 커버리지가 좋아야 합니다. 이것은 사실 진입장벽이 매우 높아서 말이 후발주자(모바일 광고 플랫폼 회사)들이 제휴한 앱들이 많지 않으면 힘듭니다. 아니면 끝판왕 하나를 제휴하던지요(카카오톡 같은 것?)

위의 앱 매체 제약 조건이 걸린다면 일반적인 PC 온라인 광고에서는 응용할 수 있는 방법은 라이프타임에 대한 모니터링을 길게 해서 상품을 추천해 주는 방법을 얼른 생각해도 할 수 있을것만 같습니다.

어떤 온라인 사용자가 추정 모델 또는 데이터온보딩(data on-boarding)으로 20대 여성이라는 것을 알고 다음과 같은 순서로 제품에 관심을 보였거나 구매를 했다면 그 다음 상황에 필요한 것을 유추해서 추천해 줄 수 있습니다.

청바지 → 워킹용 신발 → 워터프루프 화장품 → 수영복 → 카메라방수팩

다소 억지로 만든 예입니다만 저런 시퀀스가 있다면 카메라방수팩을 광고해서 구매하도록 유도할 수 있습니다.  물론 이것도 앱매체의 커버리지 문제처럼 온라인 웹페이지와 제휴가 많이 되어 있어야 하고 제품도 골고루 보여줘서 어떤 행동(behavior)를 하는지 시차를 두고 기록해 둬야 하는 문제가 있습니다. 물론 광고에 잘 반응하는 사람일 수록 하기 쉽고 그렇지 않은 사람이나 특정 쇼핑몰(G마켓 이랄지)에서만 구매를 하는 사람들이라면 조금 어렵습니다.

이런 사람들에게는 다 포기하고 조건을 만족하는 사람들에게만 해도 충분할 것 같은 느낌입니다.

필요한 상품의 세트나 연관상품의 세트는 데이터만 있다면 노출이나 클릭, 구매 기록으로부터 연관 규칙 탐사(sequence association rule mining)같은 간단한 방법으로도 정보를 추출해서 확보 할 수도 있을 것 같은데  실제로 해보지는 않았지만 간단한 시뮬레이션 정도는 해볼 수 있을 것 같습니다.

다시 앱의 문제로 돌아와서 만약 카카오톡 같은 사람들이 매우 많이 쓰는 앱이라면 사용자의 메세지 텍스트를 분석해서 (윤리적으로 그러면 안되는 것은 당연하고) 문맥을 파악한 뒤 필요한 것을 알아내서 카톡내에서 광고를 보여주고 추천해 주는 방법도 고민해 볼 수 있겠습니다. (그냥 상상입니다. 현실적으로 안되겠지요)

 

R – yaml 파일 읽어오기

R로 작성한 script에서 가끔 복잡한 설정들 읽어야 할 때가 있습니다. 여러 방법을 사용할 수 있겠지만 설정파일을 만들어 놓고 읽어서 사용하는 방식을 선호하는데 예전에는 json 포맷을 설정으로 쓰다가 너무 너저분해서 이번에 yaml으로 바꿔봤습니다.

R이 너저분해지는 이유가  이런 종류의 tree 구조의 파일을 읽어서 자료구조로 바꿀때 R에서는 list 타입을 사용해서 맵핑하게 되는데 list의 하위 아이템이 1개인 경우 다른 랭귀지와는 많이 다르게 굉장히 복잡해 집니다. 이렇게 복잡한 이유가 R에는 모든 데이터타입이 기본적으로 vector 취급되기 때문입니다.

그런데 yaml을 사용해보니 json을 사용할 때보다는 데이터타입을 훨씬 잘 변환해 주는 것 같습니다.

패키지는 yaml을 설치해서 사용하면됩니다.
전체 코드는 아래에 있습니다.

# install.packages("yaml")
require(yaml)
configuration = yaml.load_file("d:\\workspace\\test_configuration.yaml")

print(configuration)
is(configuration)  # configuration 심볼의 타입 확인

print(configuration$var_0001)  # 각각 하위 요소들의 내용 확인
print(configuration$var_0001$var_0001_01)  # 각각 하위 요소들의 내용 확인

configuration$var_0001$var_0001_01[[1]]  # 이건 여전히 문제
is(configuration$var_0001$var_0001_01[['var_0001_01_01']])
is(configuration$var_0001$var_0001_01[['var_0001_01_02']])

print(configuration$var_0002)
print(configuration$var_0003)
print(is(configuration$var_0003))

test_configuratino.yml 파일의 내용

var_0001:
  var_0001_01:
    var_0001_01_01: "value_0001_01_01"
    var_0001_01_02: "value_0001_01_02"
var_0002:
  - "value0002_1"
  - "value0002_2"
  - "value0002_3"
  - "value0002_4"
  - "value0002_5"
var_0003: True

주의할 것은 하위 항목이 1개인 것은 여전히 [[1]] index를 지정해주지 않으면 안됩니다. 그래도 JSON보다는 훨씬 쓰기도 편하고 좋은것 같습니다.

R – 변수에 값을 넣고 바로 결과를 출력하기

제목대로 입니다. 정말 별것 아닙니다. 아주 가끔 유용하게 쓸 때가 있습니다.

variable <- 2 * 3
(variable <- 2 * 3)

핵심은 2번째 줄입니다.

직접 실행해 보세요.

예전에 어떤 R 전문가들이 모여서 토론하는 메일링리스트에서 저렇게 쓰는 것을 본 적이 있어서 기억하고 있었습니다.

원리는 간단하면서도 오묘한데 R의 구조를 이해하는데도 도움이 됩니다.

R은 값을 가진 symbol이나 값 자체를 호출하게 되면 기본으로 print함수가 호출되어서 심볼의 내용을 출력하게 되어 있습니다. 그런데 <- 나 = 로 변수대입(실제로는 심볼지정)을 하게 되면 print는 기본으로 작동하지 않습니다.

그래서 연산자 심볼인 소괄호로 묶어주면 최종 연산된 값이 리턴되고 바로 print까지 실행됩니다.

저걸 쓸 일이 있겠나 싶겠지만 정말 가끔 쓸 일이 있어요. ^ㅡ^;;;


위에 제가 이해를 위해서 연산자라고 적었는데 오해의 여지가 있지 않을까하는 걱정에 내용을 추가합니다.

R에는 연산자가 없습니다. (아마도…)
다음 코드를 실행하고 결과를 확인해 보세요.

is(`[`)  # 얘는 펑션
`[`

is(`(`)  # 얘도 평션
`(`

is(`<-`)  # 얘도 평션
is(`=`)  # 얘도 평션

is(`]`)  # 하지만 얘는 펑션이 아님
`]`

is(`)`)  # 얘도 아님
`)`

닫는 괄호들은 무슨 타입인지 잘 모르겠지만 함수도 아니고 일반 심볼도 아닙니다.  아마 표현문 종료 기호같은 R 내부에서는 어떻게 취급되는지 모르겠습니다.

다음 코드도 한 번 실행해 보세요.

e <- parse(text="(1+2)")
e[1][[1]][[1]]
e[1][[1]][[2]]
e[1][[1]][[3]]
e[1][[1]][[4]]

결과는 직접 확인해 보세요.
이걸 이해하셨다면 R의 내부구조를 많이 이해한 것이 됩니다.

R – data.frame의 특정 컬럼의 NA를 0으로 채우기

별것 아닙니다만
data.frame에 NA가 섞인 경우에 이 결측치(missing value)를 채울 때 특정 컬럼의 결측치만 0으로 채워주고 싶을 때가 있습니다.
한 컬럼은 어떻게 하는 기억하실텐데요. 두 개 이상의 컬럼에 있는 NA를 모두 0으로 채우려면 apply를 써야하나? for loop을 돌려야 하나  이렇게 생각하기 쉬운데 이렇게 하면 됩니다.

index <- c("1번줄", "2번줄", "3번줄", "4번줄", "5번줄")  # 그냥 텍스트 컬럼
column1 <- c(1, 2, 3, 4, NA)  # 숫자 컬럼
column2 <- c(2, 3, 4, NA, 5)  # 숫자 컬럼
df <- as.data.frame(cbind(index, column1, column2))  # data.frame 생성

df
df[is.na(df[, "column1"]), "column1"] <- 0  # 한 컬럼의 결측치만 처리할 때는 이렇게
df

df
df[, c("column1", "column2")][is.na(df[, c("column1", "column2")])] <- 0  # 두 컬럼의 결측치를 처리할 때는 이렇게
df

Rstudio에서 실행해보고 결과를 어떻게 되는지 금방  알 수 있습니다.

R 언어의 구조적에서 [와 ]가 연산자 심볼이라는 것을 기억하면 사실 간단한 것인데 여러가지 다른 랭귀지를 섞어서 사용하다면 저 컨셉을 매번 까먹습니다.