2016년 11월 9일 수요일

RDD - Resilient Distributed Dataset

rdd (Resilient Distributed Dataset)는 사전 그대로 탄력적인 분산 데이터 집합을 말한다.
생성 후 변경이 불가능한 데이터 집합이며, 이에 따라 단순한 구조에서 오는 성능적인 이점을 가지고 있다.

rdd 에서는
map, reduce, filter 와 같은 변경 ( transformation ) 요소와 collect, count와 같은 실행 ( action ) 요소를 가진다.
실제 수행은 action 에서 발생한다.

분산 형태의 파일을 로딩 할 때,
- sqlContext.sql(“<QEURY>”), sparkContext.testFile(“hdfs://…”)
OR
로컬 collection을 parallelize 명령을 통해서,
sparkContext.parallelize(<list>, <slices number>)
rdd 가 생성 될 수 있다.

**
탐구 하기
rdd.coalesce().glom().collect()
rdd.coalesce(<partitions number>) - 원하는 파티션 수로 결합 ( reduce ) 한다.
rdd.glom() - 파티션 별로 결합된 rdd 를 돌려 준다.
rdd.collect() - driver의 메모리로 rdd 의 모든 데이터를 다 모은다.
sparkContext.runJob(<rdd>, <partition func>, <partitions>) - 원하는 partition 에만 함수를 적용한다.


참조

KNIME 도구를 통한 응용 사례 -> 사이트 본문 링크

* HIVE 와 SPARK 를 활용한 기계 학습 디자인 예제이다.
* 분산 처리 ( process )를 위한 영역에서 rdd 가 활용되는 것을 확인 할 수 있다.

HIVE 질의 하기 on SPARK

SPARK 에서 HIVE 질의 하는 과정이다.

SPARK CONTEXT 포인트를 얻는다.
from pyspark import SparkContext, SparkConf
conf = SparkConf().setAppName(‘HIVE SQL TEST01’)
sc = SparkContext(conf=conf)

HIVE CONTEXT 포인트를 얻는다.
from pyspark.sql import HiveContext
sqlContext = HiveContext(sc)

HIVE SQL 질의를 하고 결과를 가져온다.
result = sqlContext.sql("SELECT * FROM tb_test01”).collect()

PANDAS DATAFRAME 형태로 변환한다.
import pandas as pd
df = pd.DataFrame(result,columns=result[0].asDict().keys()) if len(result) > 0 else ‘nothing’

**
result 는 list 타입이고, spark 명세 row 포맷을 element 로 가진다.

뒷문은 언제나 잘 잠근다.
sc.stop()


참조

HIVE를 위한 콘솔 ( console ) CLI 사용 도구
사용자 ( end-user )에게 인터렉티브 ( interactive ) CLI 환경을 제공한다.

가. beeline
예제 :: beeline> !connect jdbc:hive2://<thrift server>:10000
SQL 문장이 바로 수행이 가능하다.

나. spark-sql
본문 방식으로 동작하며 CLI 를 제공한다.
hive metastore service를 이용하고, thrift server 와는 대화하지 않는다.

커버 사진

2016년 11월 7일 월요일

sqlite3 to hdfs with hive

sqlite3 에서 사용하던 이력 데이터의 용량이 너무 커져서 하둡 (hive)으로 옮기는 과정을 다룬다.
hive 저장 포맷에 대한 간략한 비교도 포함한다.

목차

  • sqlite3 to hdfs ( hadoop file system )
  • hdfs to hive
  • performance as hive format


sqlite3 에서 hdfs 로 파일 저장하기

sqlite3 -csv big.db “select * from big;” | hadoop fs -put - /user/me/big.csv

**
결과를 local 에 csv 로 저장 할 공간이 없어서, pipe 형식으로 하둡으로 바로 저장했다.
질의 결과를 표준 출력 ( stdout ) 으로 보낼 수 있다면 응용 될 수 있는 방법이다.

hdfs 에서 hive 로 로딩 하기

hortonworks 의 amberi 도구를 사용하면, Hive View 를 만들어서 Upload Table 메뉴를 이용한다.
미리보기 모드에서 파일 포멧, 테이블/컬럼 이름 등을 지정하면 심플하다.

sql 기반의 명령어는 다음과 같다.
테이블 스키마를 먼저 생성하고, csv 파일을 로딩한다.
CREATE TABLE big_text (Column01 int, Column02 string…) STORED AS TEXT;
LOAD DATA INPATH ‘/user/me/big.csv’ [OVERWRITE] INTO TABLE big_text;

다른 형태의 포맷으로 테이블을 만드는 과정이다.
CREATE TABLE big_orc STORED AS ORC AS SELECT * FROM big_text;

**
HIVE는 다양한 포맷을 지원한다.
sequence, text, orc, rc, parquet ..
성능 관점에서 보면 질의 형태에 따라 row 와 column 기반의 포맷에 주의한다.

특정 컬럼  filter에 있어서 text와 orc 포맷 테이블의 질의하기
>> column 기반의 orc에 이점이 있다.

hive> select count(*) from big_orc where sdate = '20160104';
Query ID = root_20161107130507_53898e98-2f58-4ca4-a4c9-ca03a527c8de
Total jobs = 1
Launching Job 1 out of 1


Status: Running (Executing on YARN cluster with App id application_1478242837204_0017)

--------------------------------------------------------------------------------
        VERTICES      STATUS  TOTAL  COMPLETED  RUNNING  PENDING  FAILED  KILLED
--------------------------------------------------------------------------------
Map 1 ..........   SUCCEEDED     20         20        0        0       0       0
Reducer 2 ......   SUCCEEDED      1          1        0        0       0       0
--------------------------------------------------------------------------------
VERTICES: 02/02  [==========================>>] 100%  ELAPSED TIME: 9.08 s  
--------------------------------------------------------------------------------
OK
673374
Time taken: 9.762 seconds, Fetched: 1 row(s)
hive> select count(*) from big_text where sdate = '20160104';
Query ID = root_20161107130524_c2dcdccb-63c1-4502-a305-6a681fa1ea9e
Total jobs = 1
Launching Job 1 out of 1


Status: Running (Executing on YARN cluster with App id application_1478242837204_0017)

--------------------------------------------------------------------------------
        VERTICES      STATUS  TOTAL  COMPLETED  RUNNING  PENDING  FAILED  KILLED
--------------------------------------------------------------------------------
Map 1 ..........   SUCCEEDED     20         20        0        0       0       0
Reducer 2 ......   SUCCEEDED      1          1        0        0       0       0
--------------------------------------------------------------------------------
VERTICES: 02/02  [==========================>>] 100%  ELAPSED TIME: 38.58 s  
--------------------------------------------------------------------------------
OK
673374
Time taken: 39.234 seconds, Fetched: 1 row(s)

참고


hive architecture figure - referred to apache hive homepage


2016년 11월 3일 목요일

구글 애널리틱스 전자상거래 - 관련 상품 가져오기

GA 전자상거래 기능인 "관련 상품" 기능을 알아 본다.
아마존 성공 사례인 상품 기반 추천의 “같이 구매한 상품들”과 유사한 기능이다.

목차
  • GA에서 기능 활성화
  • API로 데이터 가져오기
    • UI 조회 도구
    • 파이썬 도구
  • 샘플 데이터

1. GA에서 기능 활성화 하기
“관리” -> “보기” -> “전자상거래  설정” 의 관련 상품을 체크한다.


2. API 로 데이터 가져오기

가. UI 조회 도구로 확인 및 가져오기
UI 조회 도구 <- 클릭
https://ga-dev-tools.appspot.com/query-explorer/?
dimensions=ga:queryProductId,ga:relatedProductId
&metrics=ga:correlationScore,ga:queryProductQuantity,ga:relatedProductQuantity
&filters=ga:queryProductId==A
**
GA 계정으로 로그인 후에 원하는 보기를 선택한다.

나. 파이썬 도구로 확인하기
import pandas.io.ga as ga
df = ga.read_ga(
    account_id=“<계정 ID>“,
    profile_id=“<보기 ID>",
    property_id=“<속성 ID>”,
    metrics=['correlationScore','queryProductQuantity','relatedProductQuantity'],
    dimensions=['queryproductid','relatedproductid'],
    #filters=['queryproductid==A'],
    start_date="2016-10-01",
    end_date="2016-11-03",
    index_col=0
)
**
측정 기준/항목 선택은 여기를 클릭 한다.
연동 방법은 판다스에서 구글 애널리틱스 API 연동 을 참고 할 수 있다.

3. 샘플 데이터 보기


**
correlationScore 는 0 에서 1 사이의 값을 가진다.
queryproductid -> relatedproductid 의 신뢰도로 추정되고 1에 가까울 수록 연관성이 높다.
가이드에서 공식을 찾을 수 없었지만, 연관 규칙과 흡사한 것으로 보인다.

Linux Repository 만들기

hortonworks hdp 2.5 repository 가 느린 이유로 로컬  repository가 필요했다.
ambari-server 에서 cluster 구성 시에 참조하는 repository를 만드는 방법이다.

**
여기서는, 서버를 <hdp_repo> 라 이름한다.

가. repository 를 생성 도구들 설치한다.

yum -y install yum-utils createrepo

나. repository 를 위한 데이터를 다운 받는다.

reposync -r HDP-2.5
reposync -r Updates-ambari-2.4.1.0
reposync -r HDP-UTILS-1.1.0.21

**
쉽게 가기 위해 apache 의 기본 폴더인 /var/www/html 에서 작업했다.
각 호출 이름의 폴더 하위에 패키지들이 다운로드 된다.

다. repository 목차를 만든다.

create repo /var/www/html

라. httpd (아파치 웹 서버) 데몬을 구동한다.

마. repository 를 이용할 client 들에 설정을 등록한다.

hdp.repo
[HDP]
name=HDP PACKAGES
baseurl=http://<hdp_repo>
path=/
enabled=1


참조

다운로드 속도가 빠른 CentOS 6.x repository 이다.
[base]
name=CentOS-$releasever - Base
baseurl=http://centos.mirror.cdnetworks.com/$releasever/os/$basearch
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

[updates]
name=CentOS-$releasever - Updates
baseurl=http://centos.mirror.cdnetworks.com/$releasever/updates/$basearch
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

2016년 11월 2일 수요일

hortonworks 하둡 구성하기

호튼에서는
가볍게 기능적인 부분을 확인 할 수 있는 sandbox와
실제 하둡 구성을 도와주고 관리하는 ambari 기반을 제공한다.

두 가지를 구성 할 때, 주의 할 내용들을 요약한다.

  • HDP 2.5 on hortonworks sandbox
  • HDP 2.5 with Ambari 2.4

HDP 2.5 on hortonworks sandbox

sandbox는 기본 8GB 메모리를 요구한다.
hue는 기본 패키지에 없어서 추가로 설치했다.

**
hue 접속 에러 발생 시에 대응 방안이다.

가. 로그 폴더 권한 문제가 발생했다.

/var/log/hue 에 hue 소유자 권한을 준다.
> chown -R hue /var/log/hue

나. django.db 접속 관련 예외가 발생했다.

db를 재생성 한다.

테스트 db를 새롭게 생성한다.
> /usr/lib/hue/build/env/bin/hue testserver
서비스 db를 덮어쓰기 한다.
> cp /usr/lib/hue/desktop/desktop-test.db /var/lib/hue/desktop.db
hue 서비스를 재시작 한다.
> service hue restart


HDP 2.5 with Ambari 2.4

1. 전체 노드에 사전 작업을 한다.

 - 운영체제 (ex, Centos 6.5) 설치한다.
 - /etc/hosts 파일에 FQDN 이름을 정의한다.
 - 각 노드의 hostname 을 정의한다.
 - ssh-keygen 을 통해서 ambari server에서 키 인증 되도록 한다.
 - ntpd 를 설치해서 전체 노드의 시간을 동기화 한다.

2. ambari 서버를 구성한다.

3. amber UI에 접속해서 하둡 클러스터를 구성한다.


참고 이미지



2016년 10월 22일 토요일

클라우드 데이터 저장소 CLI 사용하기

클라우드에 데이터를 담아 두고, 필요할 때 간편하게 사용하는 시대이다.
다양한 공간 - 환경 - 언어에서 쉽게 접근 할 수 있는 장점을 가지고 있다.

맥이나 리눅스 환경에 익숙한 사용자들은 CLI가 주는 장점을 잘 알고 있을 것이다.
본문은 주요 데이터 저장소의 CLI 연결 정보(방법)를 요약한다.

목차

  • aws s3
  • google drive
  • google cloud storage


아마존 웹 서비스 (AWS: amazon web service) 의 S3

# CLI 설치 : https://aws.amazon.com/ko/cli/
pip install awscli
# id, key, region, output format 지정
aws configure
aws s3 help
aws s3 ls s3://mybucket
aws s3 cp s3://mybucket/myfile ./


**
language: python based
identify: bucket
pricing: per GB per Month and etc...


구글 드라이버 (Google Drive)

# CLI 설치 : https://github.com/prasmussen/gdrive
brew install gdrive
# 최초 수행 시 웹 브라우저 인증, ~/.gdrive 에 토근 생김
gdrive help
gdrive list
gdrive download


**
language: golang based
identify: account
pricing: free 15G


구글 클라우드 저장소 (Google Cloud Storage)

# CLI 설치 : https://cloud.google.com/storage/docs/quickstart-gsutil
# 설치 파일 다운로드 후,
./google-cloud-sdk/install.sh
# 환경 설정
gcloud init
gcloud help
gcloud info
gsutil help
gsutil cp gs://mybucket/file ./


**
language: python2.7 based (currently not supported python 3.x)
identify: bucket
pricing: per GB per Month and etc...


참조 이미지
구글 이미지 검색: http://www.mixturecloud.com


spark에서 aws s3 접근하기

spark standalone 모드에서 s3 접근 테스트를 시도했다.

2016년 10월 21일 기준,

스파크 홈페이지에서 hadoop 2.4 빌드 버전 가져온다.

spark-2.0.1-bin-hadoop2.4

**
하둡 2.7 버전에서는 다양한 에러가 발생했다.

s3 접근을 위한 환경 설정을 한다.

 * conf/spark-defaults.conf 에서 변경하는 방법
spark.hadoop.fs.s3n.awsAccessKeyId      <aws_accesss_key>
spark.hadoop.fs.s3n.awsSecretAccessKey  <aws_accesss_key>

 * 수행 코드에서 변경하는 방법
sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", <aws_accesss_key>)
sc.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey", <aws_accesss_key>)

**
sc : SparkContext

s3n protocol을 사용한다.

rdd = sc.textFile(“s3n://<bucket_name>/<path>”)
rdd.count()

**
최초 한번의 질의 시에 에러가 발생하고, 이후 질의 부터는 괜찮다.
SignatureVersion 문제로 차후 fix 버전이 나올 것으로 기대된다.


참조 이미지

2016년 10월 18일 화요일

MacOS에서 Spark 테스트 환경 구성

맥북에서 스파크 환경 구성 방법이다.
테스트를 위해서 마스터 노드 하나를 띄위 사용하는 기본 설정이다.
IntelliJ 도구에서 파이썬/스칼라 환경 설정을 추가로 다룬다.

목록

  • 스파크 구성
  • 도구 구성
  • 수행 예제 코드


스파크 구성

가. 미리 빌드된 맥용 스파크 다운로드
나. 압축 풀고 환경 설정
export SPARK_HOME=<스파크 경로>
export PATH=$SPARK_HOME/bin:$PATH
export PYSPARK_PYTHON=python3
export PYTHONPATH=$SPARK_HOME/python:$PYTHONPATH


도구 구성

스칼라

가. IntelliJ IDEA 설치
나. Plug-in으로 scala 설치
다. scala 기본 플랫폼 설정
Platform Setting -> SDKs : MacOS의 자바 플랫폼 위치 (자동 검색됨)
Platform Setting -> Global Library : 스칼라 플랫폼 컴파일러 + 라이브러리  위치 ( SPARK_HOME의 jars 폴더 )
라. 프로젝트 종속 라이브러리 설정
Project Setting -> Libraries : 필요 라이브러리 지정
마. 모듈 정보 확인
Project Setting -> Modules -> Dependencies

파이썬

가. IntelliJ PyCharm 설치
나. python 기본 플랫폼 설정
다. pip를 통한 패키지 관리


수행 예제 코드

스칼라

import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.mllib.fpm.FPGrowth
import org.apache.spark.rdd.RDD

object SimpleApp {
  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("Simple Application").setMaster("local")
    val sc = new SparkContext(conf)
    val data = sc.textFile("sample*.txt")

    val transactions: RDD[Array[String]] = data.map(s => s.trim.split(' '))

    val fpg = new FPGrowth()
      .setMinSupport(0.2)
      .setNumPartitions(10)
    val model = fpg.run(transactions)

    model.freqItemsets.collect().foreach { itemset =>
      println(itemset.items.mkString("[", ",", "]") + ", " + itemset.freq)
    }

    val minConfidence = 0.8
    model.generateAssociationRules(minConfidence).collect().foreach { rule =>
      println(
        rule.antecedent.mkString("[", ",", "]")
          + " => " + rule.consequent.mkString("[", ",", "]")
          + ", " + rule.confidence
      )
    }
  }
}

**
스파크를 로컬 환경으로 구동할때, 마스터를 .setMaster("local") 로 설정한다.
외부에 스파크를 활용할 때는 .setMaster("spark://master:7077") 형식이다.

파이썬

from pyspark import SparkContext, SparkConf
from pyspark.mllib.fpm import FPGrowth

conf = SparkConf().setAppName('FPGrowth Test')
sc = SparkContext(conf=conf)

data = sc.textFile("sample*.txt")
transactions = data.map(lambda line: line.strip().split(' '))
model = FPGrowth.train(transactions, minSupport=0.01, numPartitions=1)
result = model.freqItemsets().collect()
for fi in result:
    print(fi)


참조

MacOS 자체 스칼라 사용
brew install scala

Scala : 스칼라
Spark : 스파크

스파크 기본 환경
마스터 포트 : 7077
모니터링 UI : 8080


커버사진

2016년 10월 12일 수요일

맥OS <-> 오라클 접속

MacOS에서 오라클(Oracle)에 접속하는 방법을 소개한다.

  • 파이썬 cx_Oracle 인터페이스를 통한 연결
  • SQLPLUS 도구를 통한 연결


먼저 파이썬 cx_Oracle 인터페이스를 통한 접근 방법이다.

오라클에서 다음 두 가지 파일을 다운 받아서 압축을 푼다.
unzip instantclient-basic-macos.x64-11.2.0.4.0.zip
unzip instantclient-sdk-macos.x64-11.2.0.4.0.zip

압축을 풀면 다음 디랙토리가 생성된다.
instantclient_11_2

환경 변수를 등록한다.
export ORACLE_HOME=$(pwd)/instantclient_11_2
export DYLD_LIBRARY_PATH=$ORACLE_HOME:$DYLD_LIBRARY_PATH

cx_Oracle을 설치한다.
pip install cx_Oracle

**
ORACLE_HOME에 풀려 있는 파일을 참조하여 설치된다.
cx_Oracle이 호출 될때 필요한 라이브러리를 DYLD_LIBRARY_PATH에서 참조한다.

수행 예제 코드이다.
<code>
import cx_Oracle as cx

dsn = cx.makedsn(HOST, PORT, SID)
dbc = cx.connect('ecpadmin', 'ecpadmin', dsn)
print('ORACLE VERSION: ', dbc.version)
csr = dbc.cursor()
csr.execute('SELECT systimestamp FROM dual')
print('TIME: ', csr.fetchone())
dbc.close()

<output>
ORACLE VERSION:  11.2.0.2.0
TIME:  (datetime.datetime(2016, 10, 12, 12, 40, 46, 653846),)


다음은 SQLPLUS 도구를 통해서 접속하는 방법이다.

오라클에서 다음 파일을 다운 받아서 압축을 푼다.
unzip instantclient-sqlplus-macos.x64-11.2.0.4.0.zip

압축을 풀면 다음 디랙토리가 생성된다.
instantclient_11_2

환경 변수를 등록한다.
export PATH=$ORACLE_HOME:$PATH

접속 명령 예제이다.
sqlplu <user>/<password>@<host>/<sid>


**
추가로 한글 데이터 비정상 출력 (ex, ????) 해결 방법이다.

먼저 서버의 문자셋을 확인한다.
<sql>
SELECT *
  FROM sys.props$
 WHERE name = 'NLS_CHARACTERSET';
<output>
NLS_CHARACTERSET
AL32UTF8
Character set

오라클 9i 부터는 UTF8 대신에 AL32UTF8를 사용하고 있고,
NLS_LANG 환경 변수 수정을 통해서 해결 할 수 있다.

터미널 환경에서 적용하는 방법이다.
export NLS_LANG=.AL32UTF8

파이썬 스크립트에서 적용하는 방법이다.
import os 
os.environ["NLS_LANG"] = ".AL32UTF8"


참조

OCI (Oracle Call Interface)
오라클에서 제공하는 C 언어로 만든 인터페이스다.
편리하고 높은 성능과 안정성을 제공한다.

라이브러리 경로
On UNIX platforms you must ensure that LIBPATH environment variable is set properly to pick up the shared libraries at runtime. (UNIX gurus will understand here that LIBPATH actually translates to LD_LIBRARY_PATH on Solaris and Linux, SHLIB_PATH on HP-UX, DYLD_LIBRARY_PATH on Mac OS X, and stays as LIBPATH on AIX).

테스트 환경
MacOS Sierra
Python 3.5.1

2016년 10월 7일 금요일

도로명 주소 데이터 인코딩 변환

행정자치부에서 제공하는 도로명 주소가 euc-kr로 인코딩 되어 있다.
원만한 작업을 위해서 utf-8로 인코딩 하는 방법이다.

iconv -f euc-kr -t utf-8 <file-name>

**
iconv
The  iconv  program converts text from one encoding to another encoding.

도로명 주소DB

커버사진,

2016년 10월 6일 목요일

오라클 procedure 수행 로그 남기기 - 예제 코드

오라클(oracle) 환경에서 프로시저(procedure) 작업 수행 시 로그 남기는 코드이다.
로그를 남기기 위한 procedure와 수행 코드를 넣기 위한 procedure 폼 두 가지이다.

사용 방법은 다음과 같다.

작업 수행 procedure의 — start script 와 — end script 사이에 원하는 수행 스크립트를 작성한다.
작업 수행 procedure를 이름만 바꾸고 복제해서 사용하면 로그에서 자동으로 구분할 수 있도록 했다.

작업 수행 procedure 예제 코드,
CREATE OR REPLACE PROCEDURE job_proc01
IS
   err_code   VARCHAR (1024);
   err_msg    VARCHAR (1024);
   job_id     VARCHAR (1024);
   job_nm     VARCHAR (1024);
BEGIN
   job_id := TO_CHAR (SYSTIMESTAMP, 'YYYYMMDDHH24MISS.FF');
   job_nm := $$PLSQL_UNIT;
   etl_job_hist_logger (job_id,
                        job_nm,
                        'N/A',
                        'Started',
                        'N/A');

   -- START SCRIPT


   -- END SCRIPT
   etl_job_hist_logger (job_id,
                        job_nm,
                        'N/A',
                        'Ended',
                        'N/A');
EXCEPTION
   WHEN OTHERS
   THEN
      err_code := SQLCODE;
      err_msg := SUBSTR (SQLERRM, 1, 200);
      etl_job_hist_logger (job_id,
                           job_nm,
                           'N/A',
                           'Fail',
                           err_code || '::' || err_msg);
END;
/

로그 수행 procedure 예제 코드,
CREATE OR REPLACE PROCEDURE etl_job_hist_logger (xJobId        IN STRING,
                                                 xJobNm        IN STRING,
                                                 xJobDesc      IN STRING,
                                                 xJobStat      IN STRING,
                                                 xJobFailMsg   IN STRING)
IS
BEGIN
   DBMS_OUTPUT.PUT_LINE ('--------------------------------------');
   DBMS_OUTPUT.PUT_LINE ('> Job ID: ' || xJobId);
   DBMS_OUTPUT.PUT_LINE ('> Job Name: ' || xJobNm);
   DBMS_OUTPUT.PUT_LINE ('> Job Description: ' || xJobDesc);
   DBMS_OUTPUT.PUT_LINE ('> Job Status: ' || xJobStat);

   IF xJobStat IN ('Fail')
   THEN
      DBMS_OUTPUT.PUT_LINE ('> Job Fail Message: ' || xJobFailMsg);
   END IF;

   DBMS_OUTPUT.PUT_LINE ('--------------------------------------');

   INSERT INTO etl_job_hist (job_id,
                             job_nm,
                             job_desc,
                             job_stat,
                             job_fail_msg)
        VALUES (xJobId,
                xJobNm,
                xJobDesc,
                xJobStat,
                xJobFailMsg);
END;
/


**
기타 참조 사항 정리

토드 SQL 코드 정리 단축 코드 (format)
format -> command + shift + F

토드 문장 수행 단축 코드
run one statement -> command + enter
run all statements -> command + shift + enter

맥북 환경에서는 SQL Developer 보다 Toad가 안정적이고 직관적이었다.
앱스토어에서 받은 토드는 MongoDB, MySQL, PostgreSQL도 기본으로 지원한다.

DBMS_OUTPUT 설정 환경 변수 (for sqlplus)
SET SERVEROUTPUT ON;

토드에서 DBMS_OUTPUT은 AutoCommit OFF에서 확인 할 수 있었다.

2016년 9월 13일 화요일

우분투 초기 설정

서랍에 잠자던 노트북의 다양한 활용을 위해서 우분투를 설치했다.
공인 인증을 위해서 가상박스로 윈도우를 설치하고, 업무를 위해서 크롬 브라우저와 hwp 뷰어를 설치했다.

처음 우분투를 설치하면서 필요했던 내용 들을 요약한다.

1. 한글 자판 사용하기

Ubuntu 16.04에서 키보드 입력기는 기본적으로 fcitx로 설정되어 있다.
따라서 키보드 자판에서 입력 소스에 Hangul(Fcitx)를 선택한다.

자판 전환 기본은 super + space 조합이다. ( super는 윈도우 키였다. )

2. 데미안 패키지 관리

리눅스를 사용한다는 것은 패키지를 잘 관리하는 것이다.
사용 예제로 hwpviewer를 설치하는 과정이다.

가. apt 이용하는 방법

hwp 단어와 관련된 패키지를 찾는다.
apt-cache search hwp

찾은 패키지를 설치 한다.
apt install hancomoffice-hwpviewer

**
필요시에 apt 레포지토리를 등록해서 사용한다.

나. 패키지 파일을 다운받아 설치하는 방법

dpkg를 통해 설치 한다.
dpkg —install hwpviewer_9.20.0.347_amd64.deb

의존성 문제가 있을 경우,
apt -f install
을 통해서 관련 의존성 패키지를 설치한다.

3. 참고

* 데미안 패키지 관리는 레드햇과 비교해 보면 다음과 비슷하다.
rpm -> dpkg
yum -> apt

* Fcitx 란?
X 윈도우 시스템에 입력 방식 확장을 지원하는 프레임워크이다.

2016년 9월 9일 금요일

주요 SNS 공유 버튼 정리

주요 SNS 공유 버튼 가이드 모음이다.
개발 페이지에 대한 링크와 간략한 특징을 서술한다.

카카오 스토리 

접근을 위한 앱을 만들고, 앱 키를 발급 받아 사용한다.
url, text 정보를 지정 할 수 있다.

image 정보는 url 페이지의 open graph protocol을 기반으로 가져온다.

주의: url 페이지에 구성된 og 정의를 사용한다.

트위터 

페이지 정보를 기본으로 가지고 온다.

주의: image 정보는 노출 할 수 없다.

페이스북 

접근을 위한 앱을 만들고, 앱 키를 발급 받아 사용한다.
기본 공유 버튼을 제공하고 있으나,
원하는 아이콘을 사용하기 위해서는 공유 대화 상자를 활용한다.
공유 대화 상자 사용을 위해서는 앱의 설정에 도메인을 추가한다.

주의: url 페이지에 og 프로토콜을 사용한다.

다른 유효한 방법:
<a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://your_domain”>
ShareButton</a>

핀터레스트 

이미지 선별, url, description을 지정 할 수 있다.


주의: 바로 저장하는 Pin과 선별해서 저장하는 Bookmark 기능이 있다.

2016년 8월 31일 수요일

인구 통계 자료를 볼 수 있는 곳

세계 인구 조사
: 미국 인구 조사국에서 제공하는 세계 인구 통계 자료이다.

고령화 세계 보고서
: 고령화 사회로 가고 있는 지구촌에 대한 2015년 보고서이다.

세계 인구 통계 요약
: 세계 인구 통계를 매우 깔끔하게 보여 준다.

**
www.census.gov
미국 인구조사국 (United States Census Bureau)


주변국 자료에서 눈에 띄는 부분들을 요약해 본다.

중국 vs 인도
중국과 인도의 인구는 비슷하지만, 증가세는 인도가 가파르다.
평균 연령은 중국(37), 인도(27)이고 도시 인구 비율은 중국(58%), 인도(32%)이다.
중년에 들어선 중국을 젊은 인도가 빠르게 뒷따르고 있다.

일본
평균 연령 47세, 도시 인구 비율 94% 이다.
세계 최고의 고령화된 국가이며, 도시 인구 비율이 높다.
다음 고령화된 국가는 그리스, 이태리, 그리스, 포르투칼 순이다.

한국
평균 연령 41세, 도시 인구 비율 82% 이다.
태국, 마카오, 홍콩, 싱카포르 다음으로 저출산 국가이다.
이들의 공통점은 인구 밀도와 도시 인구 비율이 높다.

러시아
60대 이상 인구를 보면 여성 비율이 매우 높다.
전쟁으로 인해서 남자들이 많이 죽었다는 설이 있다.

2016년 8월 6일 토요일

플라스크(flask) 정적 페이지 및 로그 핸들 연결

플라스크에서 정적인 페이지를 연결하는 것과 로그 핸들을 추가하는 방법을 요약한다.

1. 정적인 페이지
정적인 파일들로 구성된 웹 페이지로 연결하는 방법이다.
경로 정보를 정적인 영역(static)으로 던진다.

2. 로그 핸들 연결
파이썬 로깅의 다양한 핸들 정의 후 플라스크 로거에 연결한다.
파일에 로그를 남길때 유용하다.

샘플 코드 분석를 통해서 알아본다.
import logging

from flask import Flask



app = Flask(__name__)



@app.route('/')

def static_pages(path):

    app.logger.error(path)

    return app.send_static_file(path)



if __name__ == '__main__':

    handler = logging.FileHandler('app.log', mode='a')

    handler.setLevel(logging.INFO)

    app.logger.addHandler(handler)

    app.run(debug=True)
**
<path:path>
앞에 path는 슬래쉬(/)를 포함하는 값을 의미한다.
생략 시에 기본 값인 string은 /를 포함하지 않는다.
send_static_file
접근 경로를 정적 페이지 영역으로 던진다.
logging.FileHandler
파일에 접근을 위한 핸들이다.
handler.setLevel
지정한 레벨보다 상위 레벨만 기록한다.
DEBUG < INFO < WARN < ERROR < CRITICAL
app.logger.addHandler
플라스크 로거에 핸들을 추가한다.

2016년 7월 27일 수요일

구글 애널리틱스 스팸 막기

자체 로봇 제거에도 불구하고, 다수의 스팸 패킷이 들어온다.
이를 막기 위한 좋은 방법을 소개한다.

스팸 막는 방법 두 가지 (필터 활용)

1. 포함하는 방법
다수의 스팸 사이트들이 호스트 이름과 화면 해상도가 (not set)으로 표기된다.
필터 시점에 호스트 이름의 경우 무효값으로 인지하고, 화면 해상도는 (not set)으로 인지한다.
So, 명확한 호스트 이름을 포함하는 패킷과 화면 해상도가 (not set)인 패킷을 제외하는 조건으로 필터한다.
**
무효값은 필터를 무시한다.

2. 제외하는 방법
스팸으로 판단되는 캠페인 소스에 대해서 정규식 패턴을 찾아서 제외한다.
한줄에 들어가는 정규식 패턴의 글자수가 256자로 제한이 있다.

결론

두 가지 방법을 혼용 할때, 각각의 이점을 최대한 살릴 수 있다.
1번 방식으로 다수의 스팸을 걸러내고, 나머지는 2번 방식으로 조금 명확한 기준의 정규식을 사용한다.

2016년 7월 22일 금요일

Firebase 앱분석 설치 가이드

구글에서 2014년 인수한 백엔드 서비스인 Firebase의 앱분석 설치 과정을 다룬다.

크게 보면 아래 두 가지 내용이다.
가. iOS 기반에서 firebase analytics 를 사용하는 방법
나. 구글 태그 매니저 연동 방법

먼저 iOS 기반에서 firebase analytics를 사용하는 방법이다.


맥에서 CocoaPods를 설치한다.
아마도 에러가 발생한다.
ERROR:  Error installing cocoapods:
activesupport requires Ruby version >= 2.2.2.

구글 커뮤니티는 다음 차선책을 제시한다.
sudo gem install activesupport -v 4.2.6
sudo gem install cocoapods

**
gem: 세련된 루비 패키지 관리자
CocoaPods: Cocoa 라이브러리 패키지 관리자

xcode 도구에서 개발 프로젝트를 생성한다.
프로젝트 생성 폴더에서 Firebase 라이브러리를 가져온다.
pod init :-> Podfile이 생성된다.
vi Podfile :-> pod ‘Firebase’를 추가한다.
pod install

Firebase에서 서비스 프로젝트를 생성한다.
GoogleService-Info.plist 파일을 내려받아 개발 프로젝트에 추가한다.
GoogleService-Info.plist 내용에 IS_ANALYTICS_ENABLE을 True로 변경한다.

프로젝트에 코딩 작업을 한다.
AppDelegate.swift에 가이드 코드를 추가한다.
import Firebase

func application(application: UIApplication, didFinishLaunchingWithOptions  …) -> Bool {
        // Override point for customization after application launch.
        FIRApp.configure()
        return true
    }

ViewController.swift에 이벤트 로그 코드를 삽입한다. 
import FirebaseAnalytics

FIRAnalytics.logEventWithName(“<eventName>”, parameters: [
“<keyName>”: “<keyValue>”,
… ])

Analytics 디버깅 옵션을 추가한다.
Product > Scheme > Edit Scheme… > Arguments (tab) > Arguments Passed On Launch
에 -FIRAnalyticsDebugEnabled 값을 추가한다.

<<실제 디버그 내용
2016-07-22 17:26:47.742 myFirebaseA[10445:] <FIRAnalytics/DEBUG> Logging event: origin, name, params: app+gtm, test_event, {
   "_o" = "app+gtm";
   eventAction = "test event action";
   eventCategory = "test event category";
}
2016-07-22 17:26:47.796 myFirebaseA[10445:] <FIRAnalytics/DEBUG> Event logged. Event name, event params: test_event, {
   "_o" = "app+gtm";
   eventAction = "test event action";
   eventCategory = "test event category";
}

디버그 로그로 태그 전송 여부를 추측 할 수 있다.
확실히 하기 위해서, 실시간 확인이 가능한 구글 태그 매니저를 활용한다.

다음은 구글 태그 매니저 연동 방법이다.


태그 매니저에서 iOS용 firebase 컨테이너를 생성한다.
게시 버전의 json 파일을 내려 받고, container/<code>.json 형태로 개발 프로젝트에 참조를 건다.

개발 프로젝트에 태그 매니저 라이브러리를 추가한다.
pod 'GoogleTagManager', '~> 5.0' 를 Podfile에 추가하고,
pod install 한다.

<<실제 디버그 내용
2016-07-22 17:26:47.735 myFirebaseA[10445:649284] GoogleTagManager info: Processing logged event: test_event with parameters: {
    eventAction = "test event action";
    eventCategory = "test event category";
}
2016-07-22 17:26:47.740 myFirebaseA[10445:649284] GoogleTagManager info: Sending universal analytics hit: {
    "&ea" = "test event action";
    "&ec" = "test event category";
    "&el" = "test_event";
    "&ni" = 0;
    "&t" = event;
    "&tid" = "UA-012345678-1";
}

2016년 7월 21일 목요일

블로거에 구글 태그 매니저 스니펫 추가

구글 블로거(Blogger)에 GTM 스니펫을 삽입할때 이슈와 해결 방안을 기록한다.

스니펫 코드 입력 후 저장하면 다음 알람을 접한다.

XML을 구문분석하는 중 오류 발생(1272행, 43열): The reference to entity "l" must end with the ';' delimiter.
**
XML에서 <, >, &는 tag와 entity를 표시를 위한 예약문자임으로 아래와 같이 변경한다.
< :-> &lt;
> :-> &gt;
& :-> &amp;

스니펫 코드를 구문 오류를 해결하기 위해서 아래와 같이 변경한다.

'dataLayer'?'&l :-> 'dataLayer'?'&amp;l

2016년 7월 20일 수요일

구글 애드워즈 인증 요약 노트

구글 애드워즈 인증을 준비하면서 요약한 내용들이다.
1년 후를 기약하며 흔적을 남긴다.

타게팅 방법

1. 문맥 타겟팅
    1. 키워드 및 주제를 선택한다.
    2. 검색 유형
        1. 키워드 문맥 일치
            1. 광고 게재위치가 키워드와 문맥적으로 관련이 있다.
        2. 확장 키워드 일치
            1. 광고 게재위치가 키워드 및 광고를 조회한 사용자가 최근에 검색한 페이지등과 관련이 있다.
2. 잠재고객
    1. 관심 분야
        1. 관심사나 공통 화제를 기준으로 타켓팅한다.
    2. 리마켓팅
        1. 과거 사이트 방문 여부를 기준으로 타겟팅한다.
    3. 인구통계
        1. 인구 통계 사용
3. 게재위치
    1. 게재위치
        1. 선택 게재위치를 사용하여 사이트, 모바일, 앱, 동영상을 타게팅한다.
    2. 사이트 카테고리 옵션
        1. 디스플레이 네트워크 카테고리를 기준으로 타게팅한다.
4. 입찰 옵션 두 가지
    1. 타겟팅 및 입찰
        1. 게재위치 타겟팅을 한다고 할때 키워드가 일치 함에도 게재위치가 다르면 노출이 되지 않는다.
    2. 입찰
        1. 게재위치 타겟팅을 한다고 할때 키워드와 일치하면 노출 되고, 게재위치도 맞으면 입찰 가격을 올릴 수 있다.


비용 지불 방식

1. CPC
    1. 클릭수를 늘리는 것이 목표
    2. 자동 입찰 전략
        1. 일일예산을 설정하면 자동으로 입찰가 관리
    3. 수동 입차 전략
        1. 광고그룹, 개별 키워드, 게재위치별로 입찰가 지정 가능
2. ECPC
    1. 기기, 브라우저, 위치, 시간대 등 실시간 정보와 기존 전환값을 비교해 입찰가를 조정한다.
3. vCPM
    1. 조회 가능 노출 1000회당 비용으로 인지도 향상이 목표
    2. 키워드 뿐 아니라 게제위치를 타겟팅 가능함으로 관심이 있는 고객에게 노출 할 수 있다.
4. CPA
    1. 타겟 전환당 비용은 전환을 늘리는 것이 목표
    2. 전환 액션에 따른 전환 코드를 심어야 한다.
    3. 캠페인은 검색 네트워크, 디스플레이 네트워크 또는 둘다 타겟팅하고 있어야 한다.
5. ROAS
    1. 설정된 비용 안에서 ROI (투자 수익)을 최대로 이끌어 낸다.
    2. ROAS를 사용하는 모든 광고 그룹 또는 캠페인에 보고된 기존 전환값을 활용한다.


전환추적 방법

1. 코드 없는 전환추적
    1. Google이 Play 스토어를 소유하고 있기 때문에 앱 다운로드 정보를 제공할 수 있다.
2. SDK 전환 추적
    1. SDK를 통해서 앱에 이벤트를 삽입하는 방법이다.
3. 서버 간 전환추적
    1. 다음 SDK의 단점을 개선 할 수 있다.
        1. SDK를 이용한 방법이 어렵고, 앱이 무거워 질 수 있다.
        2. 전환코드를 잘 못 구현된다면, 앱에서 버그가 발생 할 수 있다.
        3. 변경 코드 반영 시, Play 스토어 검토 과정에서 지연이 발생 할 수 있다.
4. 앱 설치 확인 솔루션
    1. 외부 솔루션을 이용한다.


광고 갤러리

1. 동적 광고
    1. 사용자의 위치 및 표시되는 내용에 일치하는 리치미디어 광고이다.
    2. 라이트박스 광고
    3. 확장형 리치 미디어 디스플레이 광고이다.
    4. 다양한 양방향 형식을 통해 고객의 참여를 유도할 수 있다.
    5. DoubleClick Studio를 사용하면 쉽게 리치 미디어 광고와 동적 소재를 제작할 수 있습니다.
2. 동영상 광고
3. 일반 용도 광고
4. Gmail 광고


디스플레이 캠페인 최적화 (타겟팅 최적화)

1. 공격적인 (aggressive)
    1. 1달에 15건 이상의 전환이 있을때 사용할 수 있다.
    2. 기존의 전환 데이터를 기반으로 최적화하며, 실제 적용된 예산을 조금 초과 할 수 있다.
2. 보수적인 (conservative)
    1. 정해진 키워드와 일치하는 것만 찾는다.
    2. 적용 예산을 초과하지 않는다.


애드워즈 도구

1. 아이디어를 얻을 수 있는 방법을 제공한다.
    1. 키워드 플래너
    2. 디스플레이 플래너
    3. 광고 미리보기 및 진단

구글 태그 매니저의 맞춤 자바스크립트 활용 예제

구글 태그 매니저에서 {{출생년도}}라 정의한 데이터 레이어 변수를 전달 받는다고 가정하자.
전달 받은 값을 가공할 필요가 있을때, 맞춤 자바스크립트를 통해서 간편하게 적용 할 수 있다.

다음은 {{출생년도}} 변수를 {{연령대}}변수로 가공하는 맞춤 자바스크립트 코드이다.
: {{출생년도}}를 '19880917'를 받았을때, {{연령대}}가 '20대'가 된다.

<<EOF
function (){
    // 태어난 년도를 기준으로, 연령대를 계산한다.
    var paramYear={{출생년도}};
    if ( paramYear === '' || isNaN(paramYear) ) {
        // 빈값이거나 숫자가 아니면, 오류로 보고 제외한다.
        return;
    } else {
        // 한국 나이를 기준으로, 연령대를 매핑한다.
        var currentYear=parseInt(new Date().getFullYear()); 
        var bornYear=parseInt(paramYear.substr(0,4));
        var age = currentYear - bornYear + 1;
        if ( age <= 0 || age > 200 ){
            // 미래에서 온 사람과, 200세 이상의 사람은 오류로 본다.
            // 기네스북: 역사상 가장 오래 산 사람은 1997년에 122세 나이로 세상을 뜬 프랑스 여성
            return;
        }
        var userAges;
        switch ( parseInt( age / 10 ) ){
            // IF 반복을 제외하는 이점이 크다고 본다.
            case 0:
                // 희박한 경우라 정렬을 고려하지 않고, 가독성을 높인다.
                userAges = "10대미만";
                break;
            case 1:
                userAges = "10대";
                break;
            case 2:
                userAges = "20대";
                break;
            case 3:
                userAges = "30대";
                break;
            case 4:
                userAges = "40대";
                break;
            case 5:
                userAges = "50대";
                break;
            case 6:
                userAges = "60대";
                break;
            case 7:
                userAges = "70대";
                break;
            default:
                userAges = "80대이상";
        }
        return userAges;
    }
}
EOF

2016년 7월 14일 목요일

구글 애널리틱스 유용한 기능 요약

구글 애널리틱스 사용 시, 자주 사용하는 유용한 기능들을 요약한다.

컨텐츠 그룹
컨텐츠 그룹의 규칙 그룹들을 페이지 URL에 기반한 패턴을 정의한다.
(2016년 7월 1일 기준, 무료 5개 제공)
**
컨텐츠 그룹의 규칙 그룹 단위로 행동 흐름(방문형태)를 한눈에 볼 수 있다.

측정 기준
hit, 세션, 사용자, 제품 범위의 측정 기준을 제공한다.
(2016년 7월 1일 기준, 무료 20개 제공)
**
성별, 연령, 로그인 여부 등의 확장 기준들을 손쉽게 추가 할 수 있다.

채널 그룹
기본 채널 이외에 맞춤 채널을 만들 수 있다.
사이트로 유입 될때, 식별 가능한 정보의 패턴으로 정의 한다.
**
특정 유입 경로(채널)를 그룹화 식별 할 수 있다.

세그먼트
리포트는 세그먼트 단위로 분리해서 볼 수 있다.
조건 필터의 경우 ‘세션’과 ‘사용자’ 단위임에 주의한다.
**
리포트 결과를 다양하게 분류 하여 볼 수 있고, 갤러리를 통해서 공유 할 수 있다.

고급 필터
세그먼트가 전체 데이터에 대한 분류 그룹을 제공하는데 비해서,
이 것은 보고서의 결과 데이터를 여과한다.

맞춤 자바스크립트 변수 (태그 매니저)
HTML 구성 요소를 파싱하여 변수로 사용 할 수 있다.
상품 상세 페이지들에 경로가 아닌 상품 이름을 측정 기준으로 사용할 때 유용하다.
**
예제)
본문 중에,
<h2 id=“test_id”>상품 이름</h2>
맞춤 자바스크립트,
function() {
  var elem = document.getElementById(“test_id”);
  return elem.innerText;
}

사용자 ID (User ID)
기본적으로 제공되는 Client ID는 기기나 브라우저 별 익명으로 식별한다.
웹 : 최초 접속때 생성되고 1차 쿠키에 2년간 유지 된다.
모바일 : 설치된 어플리케이션의 최초 인스턴스 구동 시에 무작위로 생성된다.
이는, 접속 인스턴스를 기반으로 행동 패턴을 추적하는 것을 말하며, 재생성 시에 사용자 정보 또한 갱신된다.
User ID는 회원 코드를 활용하여 (접속 인스턴스에 종속되지) 않는 통합 관점의 사용자 행동 패턴을 추적하는 방법을 제공한다.


목표 시각화
목표 도달을 한 눈에 볼 수 있는 두 가지의 흐름 시각화를 제공한다.

유입경로 시각화
 - 지정한 단일 유입 경로를 표현한다.
 - 세션에 유입 위치가 있으면 순서에 관계 없이 지정한 유입 경로로 이루어진 것으로 본다.
 - 목표 지정 이후 부터 데이터가 쌓인다.

목표 흐름
 - 루프를 포함한 실제 유입 경로를 표현한다.
 - 기존 데이터를 소급하여 바로 보여준다.

공통
 - 무료 버전에서 수집 데이터 집계는 하루 정도 소요된다.
 - 세션 단위 집계로 1 세션에서는 1회 목표 도달된 것으로 표현된다.


향상된 링크 기여
* 특정 페이지의 2개의 다른 링크가 같은 하나의 페이지로 갈때,
* 특정 페이지에서 같은 하나의 링크가 상황에 따라 다른 페이지로 갈때,
와 같이, 더 향상된 인페이지 분석이 필요 할때 사용한다.

애널리틱스의 속성 설정에서 변경하고 사이트에 태그를 추가한다.
태그 매니저에서는 태그의 고급 속성에서 “거짓”을 “참”으로 변경한다.


구글 웹마스터 도구 (Search Console)
구글 검색엔진에서 어떤 검색어에 의해서 웹사이트의 어떤 페이지들이 얼마나 노출 되고 클릭 되는지를 보고한다.
구글 웹마스터 도구와 계정 연결이 필요하다.
웹마스터 도구와 웹사이트를 연결하기 위해서는 사이트 소스 접근 권한이 필요하다.


2016년 7월 4일 월요일

구글 애널리틱스에서 알 수 없는 값 요약

구글 애널리틱스에서 알 수 없는 값에 대한 처리를 어떻게 하는지 정리한다.


먼저, 실시간 이벤트를 통해서 리포트에 보여지는 내용을 본다.

**
이벤트 라벨에 empty string (‘’), null, undefined 를 입력한 결과이다.
empty string과 undefined는 (not set)으로 보여진다.
null은 null이라는 값으로 보인다.

위 결과에서,
이벤트 액션과 같이 리포팅 될 때는 알 수 없는 값을 표현할 때 쓰인다.
이벤트 라벨 스스로를 측정 기준으로 할 때는 null에 대한 값만 리포팅 된다.


가끔 접하는 알 수 없는 값에 대해서 알아본다.

(none)은 없다는 것으로 정의된 값이다.
예를들면) (direct)/(none) 웹 브라우저의 URL 타이핑을 통해서 접속한 것을 말한다.

(not set)은 식별 할 수 없는 값이다.
예를들면) (direct)/(not set) 이메일, 뉴스레터, 내부 웹 사이트처럼 GA에서 식별 할 수 없는 비 온라인 매체에서 접속한 것을 말한다.

(not provided)는 의도적으로 제공되지 않는 값이다.
예를들면) organic/(not provided) 구글에 로그인 되어 있는 사용자의 개인 정보 보호를 위해 키워드를 제공하지 않을 때를 말한다.


알수 없는 값에 미묘한 차이를 알아본다.

맞춤 측정 기준의 세션이나 사용자 범주(scope)를 볼때, empty string과 undefined는 차이를 보인다.
둘다 없는 값(not set)을 뜻하지만, empty string은 값이 없다라는 것을 덮어 쓰고, undefined는 아무런 영향을 주지 않는다.
이는 세션 이상의 범주에서 결과에 영향을 미치게 된다.
따라서, 태그에 특정 키에 값을 실어 보낼때, 특정 키를 보내지 않는 drop 효과를 가지기 위해서는 undefined 처리가 필요하다.
function() {
      if ( {{측정기준_X}} === '') {
            return;
      } else {
            return {{측정기준_X}};
      }
}
**
javascript에서 비교 조건 ==은 타입 변환한 결과 비교를 허용한다.
string 10과 int 10은 true이다.
But, === 에서는 타입이 일치 하지 않아서, false 이다.

2016년 7월 1일 금요일

구글 애널리틱스 맞춤 보고서 용어 정리

맞춤 보고서를 작성하다 보면 용어에 대한 명확한 정의가 중요합니다.
본문은 매번 혼동되는 용어를 정리하는 것에 목적을 둡니다.

아래 공식 가이드를 참조해서 핵심만 요약 합니다.
맞춤 보고서 공식 가이드

세션 수
조회 유형에 관계없이 세션의 첫 번째 조회와 함께 누적됩니다.
세션은 30분(디폴트)의 시간이 경과 하거나, 하루가 지나는 시점에는 종료된 것으로 간주합니다.
어떤 캠페인을 통해 사이트에 들어 왔다가 떠난 후 다른 캠페인을 통해서 다시 방문하면 새로운 세션으로 간주합니다.

방문자 수
세션의 첫 번째 페이지뷰와 함께 누적됩니다.

사용자
기간 설정에 따라 집계가 변합니다.

활성 사용자
특정 날짜를 기준으로 과거 N 번째 일 동안, 처음 세션을 시작한 순 사용자를 말합니다.

총 방문자 수
세션 또는 방문자 수와 연결 지을 수 있습니다.

순 방문자 수
사용자 수와 연결 지을 수 있습니다.

평균 세션 시간
한 세션의 평균 길이입니다.

평균 페이지에 머문 시간
사용자가 평균 페이지에 머문 시간입니다.

페이지에 머문 시간
연속된 페이지 조회의 시작 시각을 기준으로 계산합니다.

방문수
귀하의 사이트를 방문한 횟수입니다.

사용자 측정 항목 집계 방법 요약
가. 기간에 대한 측정 항목 (페이지뷰 수, 화면 조회수…) 등은 이전 데이터표와 합산합니다.
나. 비기간 측정 기준 (브라우저, 도시, 소스) 등은 요청 할때마다 원시 세션표의 데이터를 참조합니다.
**
비기간 일부 측정 기준 (소스, 매체) 등은 동일 사용자가 여러 버킷에 포함될 수 있어서 사용자의 총계와 합계에 차이가 있을 수 있습니다.

잠재 고객 - 개요 리포트 
측정 항목에서 사용자 기준으로 보면, 그래프에 나오는 값은 특정 시점 (시/일/주/월) 단위로 통계를 낸다.
하단에 요약 값은 그래프에 전체 기간을 기준으로 통계를 낸다.
**
그래프 기간에 신규 사용자의 합은 종합과 일치하지만 재 방문자의 합은 중복이 있다면 합이 종합과 일치하지 않을 수 있다.


2016년 6월 15일 수요일

판다스에서 구글 애널리틱스 API 연동

파이썬 라이브러리인 판다스의 구글 애널리틱스 API 사용 방법이다.
참고에 링크한 “판다스 구글 애널리틱스 연동” 가이드로 부족한 부분에 집중한다.

크게 보면,
1. 구글 개발 콘솔에서 접속 앱을 만든다.
2. 접속 앱에서 다운로드한 JSON 파일을 판다스 라이브러리 IO 폴더에 위치 시킨다.
3. 잘 활용한다.


테스트된 환경은 다음과 같다.

* 코드 호환성 문제로 파이썬 2.7에서 수행 했다.
* 판다스는 최신 버전인  0.18.1을 사용했다.
* 구글 인증을 라이브러리의 특정 버전을 설치한다.
pip install --upgrade oauth2client==1.4.12

**
구글 애널리틱스의 수집할 대상을 구분하기 위해서 하기 정보가 필요하다.
구글 애널리틱스 “관리”에 각각의 설정 변경 화면에서 모두 찾을 수 있다.
* account_id: 계정 ID
* property_id: 추적 ID (속성)
* profile_id: 보기 ID


가이드에 나오는 샘플 코드이다.
import pandas.io.ga as ga



df = ga.read_ga(

    account_id="12345678",

    profile_id="123456789",

    property_id="UA-12345678-1",

    metrics=['users', 'pageviews'],

    dimensions=['day'],

    start_date="2016-06-01",
 
    end_date="2016-06-14",

    index_col=0

)
print(df)


참고 



커버 사진

2016년 6월 9일 목요일

맥북에서 80 포트 포워딩

맥에서 주요 포트들은 보안으로 잠겨 있어서, 필요 시에 다음과 같이 패킷 포워딩 기법을 사용한다.

패킷 포워딩을 위해서 pfctl 도구 사용 예제이다.


명세한 포트 포워딩 적용하기
echo "
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 5000
" | sudo pfctl -ef -

**
웹 접근의 기본 포트인 80 포트로 들어오는 모든(any) 패킷을 로컬의 5000번 포트로 던진다.

모든 포트 포워딩 제거하기
sudo pfctl -F all -f /etc/pf.conf

포트 포워딩 룰 확인 하기
sudo pfctl -s nat

정적으로 사용하는 방법
1. /etc/pf.anchors/ 위치에 설정 파일 구문 추가
2. /etc/pf.conf 에 추가한 설정 파일 로드 구문 추가

참조


pfctl
: control the packet filter (PF) and network address translation (NAT) device.
The pfctl utility communicates with the packet filter device. It allows ruleset and parameter configuration and retrieval of status information from the packet filter.

Mac pfctl Port Forwarding

2016년 6월 3일 금요일

Pycharm에서 Golang 사용 환경 구성하기

파이참(PyCharm) 사용자가 맥에서 Go 언어에 대한 환경 구성하는 과정이다.

설치


홈페이지 주소 : https://golang.org

가. Golang을 다운로드 및 설치 한다.
 => 기본 경로은 /usr/local/go 이다.
 => 도구 설정 시 사용 될 “Go SDK 경로”가 된다.

도구 설정 ( Pycharm )


가. “설정” / “플러그 인” 에서 “Go”를 추가한다.
 => 재 시작 하면 “Go” 플러그인 관련 UI가 생성된다.

나. “설정”에서 “Go SDK 경로”를 설정 한다.
 => Go가 있는 위치를 지정하면, “버전” 정보가 표시된다.

다. “Run”에서 “go run <file_name>” 형태로 실행된다.

2016년 5월 31일 화요일

구글 태그 매니저

구글의 태그 매니저 사용 하면서 정리한 내용 입니다.

주요 기능

실시간 디버깅이 가능한 미리보기 도구를 제공한다.
변경 사항에 대한 체계적인 버전 관리가 가능하다.
다양한 분석 제품군을 기본 지원하고, 사용자 맞춤 태그 또한 지원한다.
구글 계정 단위 협업 기능을 제공한다.

권장 사항

페이지에서 발생되는 변수들은 가능하다면 데이터 레이어(dataLayer)를 이용한다.
전역변수나 DOM의 경우 유지보수 하면서 변경 가능성이 높다.
스니펫(추적 코드)는 호환성을 높이기 위해서  <BODY> 바로 다음에 추가한다.
분석 제품 추적 ID와 같이 자주 사용하는 값들은 변수에 등록해서 사용한다.

변수 설정 예제

자바 스크립트 전역 변수 선언
globalVariable = 10;
반대로, 지역 변수는 var를 붙인다.
var localVariable = 10;

데이터 레이어 변수 생성
dataLayer.push({‘key’:’value’})

데이터 레이어 이벤트 생성
dataLayer.push({‘event’:’event_name’})

**
dataLayer는 스니펫에서 정의되어 있는 예약어이다.
스니펫 코드에서 다음 위치 이름 수정(new_dataLayer_name)으로 변경 가능하다.
… (window,document,'script’,’new_dataLayer_name,’GTM-XXXX') …

맞춤 자바스크립트 변수 선언 (함수 반환값)
function() {
var now = new Date();
return now.getTime();
}

이벤트 수집 예제

분석 제품군: 구글 어낼리틱스 사용 가정

1. [웹 사이트] 이벤트 코드 삽입
    : dataLayer.push({‘event’:’event_test’})

2. [태그 매니저] 이벤트 이름이 event_test인 조건에 트리거 생성

3. [태그 매니저] 생성한 트리거에 따라 전송될 이벤트 정보 등록
    : 이벤트 카테고리, 작업(액션), 라벨 …

4. [태그 매니저] 미리 보기 및 디버깅 도구 실행

5. [웹 사이트] 이벤트 코드 수행 후 전송 확인

6. [구글 어낼리틱스] 실시간 이벤트 확인

7. [태그 매니저] 게시 (태그 적용)

구글 애드워즈 연결

리마케팅
리마케팅 목록을 등록한다.
리마케팅 스니펫 코드가 제공된다.

전환추적
전환 여부를 확인한다.
전환 스니펫 코드가 제공된다.

**
스니펫 코드는 웹 페이지에 직접 삽입 하거나,
식별 코드 정보를 통해서 태그 매니저에서 생성 할 수 있다.

주요 용어

계정
컨테이너를 그룹으로 관리한다.

컨테이너
웹/모바일 환경에 따른 추적 태그 생성 단위이다.
컨테이너를 기반으로 트리거, 태그, 변수의 설정 값이 관리된다.

버전
변경 환경에 버전 관리 기능을 제공한다.

관리자
사용자 권한 관리 및 컨테이너 관리 기능을 제공한다.
“컨태이너 가져오기/내보내기” 기능을 통해서 설정 환경을 다른 계정으로 복제 할 수 있다.

트리거
태그 발송(Fire)을 위한 조건을 명세한 트리거들을 만든다.

태그
기본 및 생성한 트리거로부터 유발된다.
사용할 제품으로 발송할 정보를 만든다.

변수
기본 변수에 사용자 변수를 정의 추가한다.
사용할 제품의 식별자를 상수로 정의하면 편리하다.

측정 기준 조회 범위

조회
값이 설정된 단일 조회에 적용된다.

세션
단일 세션의 모든 조회가 최종 값으로 적용된다.

사용자
현재 단일 세션의 모든 조회가 최종 값으로 적용된다.
변경이 없다면 미래 세션의 조회로 적용이 지속된다.

잘 작성된 참고 자료

참고

구글 태그 매니저 개발 가이드

표지 그림


2016년 5월 27일 금요일

딥러닝 메모

딥러닝을 이해하기 위해 참조한 내용들을 정리한다.


역사 

사람의 신경망을 본 뜬 인공신경망 기술이 핫 이슈가 된다.
XOR 문제에서 좌절을 안긴다.

(미래에서 온 인류 저항군인) 민스키 교수의 두 마디에 의해 암흑기로 들어간다.
* 다계층 퍼셉트론 (MLP)를 사용하면 풀수 있다.
* 지구상에 누구도 MLP 노드를 학습시킬 좋은 방법을 찾지 못했다.

폴의 오차역전파법 논문에서 MLP의 노드 학습 방법을 찾는다.
크게 관심을 끌지 못한다.

힌튼 교수에 의해서 재발견 되고 관심이 촉발 되지만,
많은 수의 은닉 층에서 학습 능력이 떨어지는 단점과 함께 제 2의 암흑기를 겪는다.

지속적인 연구 끝에 적절한 초기 값(가중치)을 부여하는 것을 통해서 문제를 해소한다.
관심 촉발을 위해서 “딥러닝”이라는 단어를 사용한다.

다양한 과제 영역에서 성과들이 나오면서 전성기를 맞이한다.


**
신경세포 - Neuron
신경계를 구성하는 주된 세포이다.

자극전달 - impulse
일정 이상의 자극 ( 역치 : Threshold )이 주어 지면 전기 신호를 발생한다.

연접 - synapse
한 뉴런에서 다른 세포로 신호를 전달하는 연결 지점이다.

인공신경망 - artificial neural network
생물학적 신경망에서 영감을 얻은 통계학적 알고리즘이다.

딥 러닝 - deep learning
여러 비선형 변환기법의 조합을 통해 높은 수준의 추상화를 시도하는 기계학습(machine learning) 알고리즘의 집합으로 정의 되며, 큰틀에서 사람의 사고방식을 컴퓨터에게 가르치는 기계학습의 한 분야라고 이야기 할 수 있다.

기계학습 - Machine Learning
어떠한 태스크(T)에 대해 꾸준한 경험(E)을 통하여 그 T에 대한 성능(P)를 높이는 것, 이것이 기계학습이라고 할 수 있다. - by Tom M. Mitchell

오차역전파법 - back-propagation
네트워크에 기대되는 모든 가중치를 통해 손실함수의 값이 최소화가 되는 최적화 가중치를 추출하는 방법론이다.

손실함수 - loss function
사건(기술적으로 표본 공간의 한 요소)을 그 사건과 관련된 경제적 손실을 표현하는 실수로 사상하는 함수이다.

합성곱 신경망 - Convolutional Neural Network : CNN
최소한의 전처리(preprocess)를 사용하도록 설계된 다계층 퍼셉트론(multilayer perceptrons)의 한 종류이다.
영상, 음성 분야 모두에서 좋은 성능을 보여준다

퍼셉트론 - perceptron
인공 신경망의 한 종류로서 각 노드의 가중치와 입력치를 곱한 것을 모두 합한 값이 활성함수에 의해 판단되는데, 그 값이 임계치(보통 0)보다 크면 뉴런이 활성화되고 결과값으로 1을 출력한다. 뉴런이 활성화되지 않으면 결과값으로 -1을 출력한다.


참고

인공신경망 백서

인공신경망 동영상

인공신경망 아이디어 ( A -> B, C -> D )


2016년 4월 29일 금요일

맥북에서 Bootable CentOS USB 만들기

맥북에서 부팅되는 CentOS USB 드라이브 만드는 방법이다.

1. CentOS 홈페이지에서 원하는 IOS 이미지를 내려 받는다.
 - https://www.centos.org/download/

2. hdiutil을 이용해서 UDRW 형태 이미지로 변형한다.
# hdiutil convert -format UDRW -o temporary.img CentOS-xxxx.iso

**
UDRW - UDIF read/write image

3 dd를 통해서 이미지를 굽는다.
설치할 디스크 장치명 확인
# diskutier list
대상 디스크 언마운트 하기
# diskutil unmountDisk /dev/diskX
2번 과정에서 만든 이미지를 굽기
# sudo dd if=temporary.img.dmg of=/dev/diskX bs=1m

**
CentOS 6.7 기준 실제 작업한 내용
$ diskutil list
/dev/disk0 (internal, physical):
/dev/disk1 (internal, virtual):
/dev/disk2 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *15.6 GB    disk2
   1:                 DOS_FAT_32 UNTITLED 1              15.6 GB    disk2s1
$ time sudo dd if=target.img.dmg of=/dev/disk2 bs=1m
Password:
3715+0 records in
3715+0 records out
3895459840 bytes transferred in 5414.762327 secs (719415 bytes/sec)

real 90m23.357s
user 0m0.024s
sys 0m54.548s

90분이 소요 되었다.
더 낳은 USB를 사용 해보니 결과는 7분 정도로 가능했다.

real 6m58.033s
user 0m0.020s
sys 0m18.291s

2016년 4월 1일 금요일

이미지에 자바스크립트 코드 삽입하기

BMP 이미지에 자바스크립트 코드를 삽입하는 과정이다.

1. 테스트로 사용할 이미지를 구한다. (sample.bmp)
2. BMP 포맷의 특징을 활용해서 자바스크립트 코드를 삽입한다.
3. HTML에서 이미지와 자바스크립트의 소스로 변경된 이미지를 가져온다.

구현된 파이썬 코드를 통해서 알아보자.

# 구글 이미지 검색에서 찾은 BMP 이미지 파일을 sample.bmp로 명명하였다.
original_file = "sample.bmp"
cracked_file = "cracked.bmp"

# 삽입될 바이너리 형태의 코드로 알림 창을 띄우는 예제를 만들었다.
script_text = 'alert("{0} is cracked.")'.format(original_file).encode('ascii')

def script_into_bmp(script_text, original_file, cracked_file):
    """
    bmp 이미지에 script 코드를 삽입하기
    :param script_text: 삽입할 자바스크립트 코드
    :param original_file: 원본 bmp 이미지 파일 이름
    :param cracked_file: 생성될 bmp 이미지 파일 이름
    :return: 성공
    """

    # 1번째 과정 : 주석 영역에 문제를 일으킬수 있는 */ 문자를 제거한다.
    with open(original_file, "r+b") as f:
        buff = f.read()
        buff.replace(b'\x2A\x2F', b'\x00\x00')  # */ 공백 치환

    # 2번째 과정 : 비트맵의 헤더 2 바이트 이후에 주석 시작 코드(/*)를 삽입한다.
    with open(cracked_file, "w+b") as f:
        f.write(buff)
        f.seek(2, 0)
        f.write(b'\x2F\x2A')  # /*

    # 3번째 과정 : 파일의 끝에 주석 끝 코드(*/)와 함께,
    # 비트맵의 헤더 BM=1;과 같이 처리하기 위해서 다음 코드(=1;)를 추가한다.
    # 테스트를 위해서 알림창을 띄우는 자바스크립트 코드를 추가한다.
    with open(cracked_file, "a+b") as f:
        f.write(b'\x2A\x2F\x3D\x31\x3B')  # */=1;
        f.write(script_text)

    return True

HTML에서 이미지를 보여주는 것과 동시에 숨겨진 자바스크립트 코드를 실행한다.
<img src=“cracked.bmp”/>
<script src=“cracked.bmp”/>

실행 화면



2016년 3월 31일 목요일

구글 애널리틱스 플랫폼 활용

구글 애널리틱스 플랫폼을 탐색하는 데모와 도구들을 제공하는 페이지이다.

https://ga-dev-tools.appspot.com

다음과 같이 흥미로운 기능들을 가이드 하고 있다.

  • GA 측정기준 및 측정항목을 탐색할 수 있다.
  • 질의 도구를 통해서 통계 데이터를 조회할 수 있다. 
  • 구글 문서(스프레드시트)에서 주기적으로 갱신 가능한 리포트를 생성할 수 있다.
  • 강력한 내장 API들을 활용하여 손쉽게 사용자 솔루션을 만들 수 잇다.
  • 사이트 외부에도 삽입할 수 있는 추적코드 생성 도구를 제공한다. (1)

특히 (1)번을 통해서 다양한 행위에 대한 통계 자료를 손쉽게 모을 수 있다.
예를 들면,
이메일 공지에 대한 반응을 조사한다고 할때 다음과 같은 코드를 HTML 메일에 심어서 발송한다면, 메일 수신자에 대한 반응 확인이 가능하다. 나머지는 상상의 나래를 펼쳐보자.

-- sample code --
<img src="http://www.google-analytics.com/collect?v=1&t=event&tid=UA-XXXXX-1&cid=1&ec=email&ea=click&el=notice&ev=100”>

2016년 3월 18일 금요일

행렬 인수분해 3가지

인수분해는 노이즈 제거 및 데이터 압축 기법으로 유용하게 활용된다. 근래에는 기계학습 붐과 함께 패턴인식 분야에서도 유용하게 쓰인다.
본문은 일반적으로 사용하는 인수분해 기법(PCA, SVD, NMF)를 활용한 예제를 다룬다.

먼저 실험에 사용할 이미지 20개다.


위 이미지 중 하나는 45x40 이고, 일렬로 나열하면 1x1800 이 된다.
20개의 이미지를 합치면 다음과 같이 20x1800의 이미지로 만들수 있다.
(20개 이미지로는 육안 상의 의미 전달이 약해서 출력을 5번을 반복했다.)
성분의 수를 1개로 지정할때 변형(인수분해된 값을 복원)된 이미지다. 노이즈가 제거된다.
**
n_components (성분 수)
scikit-learn의 PCA, SVD, NMF의 필수 입력 인자이다.
PCA에서는 주요 인자의 개수이고 SVD에서는 S(시그마)의 인자 개수이고, NMF에서는 W, H의 특징의 개수이다. 값이 작을 수록 핵심 요소만 부각되고, 보관할 사이즈가 줄어든다.

성분 값 20, 1의 2가지의 복원된 이미지 값을 보자.
성분 값이 20일때,

성분 값이 1일때,
**
PCA, SVD, NMF 모두 유사한 형태를 보인다.
위에서 부터 PCA, SVD, NMF 순서대로 나열했다.

활용적인 측면에서는 개성있는 다양한 사람들의 사진에서 공통적인 요소를 부각해 사람이라는 객체의 일반적인 형태를 만들어 낼 수 있다는 점이다. 이 것은 다른 객체들에도 동일하게 적용 가능하다.


참조

사진 출처 및 영감을 받은 사이트
http://darkpgmr.tistory.com/110

주성분 분석(主成分分析, Principal component analysis; PCA)
고차원의 데이터를 저차원의 데이터로 환원시키는 기법이다. 서로 연관 가능성이 있는 고차원 공간의 표본들을 선형 연관성이 없는 저차원 공간(주성분)의 표본으로 변환하기 위해 직교 변환을 사용한다. 주성분의 차원수는 원래 표본의 차원수보다 작거나 같다.
**
각 성분(벡터 방향, 차원, 속성)의 평균 지점을 0으로 만드는 지점(점)으로 부터의 성분별로 거리를 추출하고 성분의 분산이 가장 큰 순으로 정렬한다.
n_components = min(n_samples, n_features)
n_components는 성분의 개수이다.

특이값 분해(Singular Value Decomposition, SVD)
행렬을 특정한 구조로 분해하는 방식으로, 신호 처리와 통계학 등의 분야 에서 자주 사용된다.
**
A = U(투영회전,직교형렬) x S(형태변환,대각형렬,components) x V(회전,직교형렬)
모든 m x n 행렬에 대해 적용 가능함으로 유연하게 쓰인다.

음수 미포함 행렬 분해(Non-negative matrix factorization, NMF)
음수를 포함하지 않은 행렬 V를 음수를 포함하지 않은 행렬 W와 H의 곱으로 분해하는 알고리즘이다. 행렬이 음수를 포함하지 않는 성질은 분해 결과 행렬을 찾기 쉽게 만든다. 일반적으로 행렬 분해는 정확한 해가 없기 때문에 이 알고리즘은 대략적인 해를 구하게 된다. 음수 미포함 행렬 분해는 컴퓨터 시각 처리, 문서 분류, 음파 분석, 계량분석화학, 추천 시스템 등에 쓰인다.
**
A = W * H
n_components = min(n_samples, n_features)
다른 기법에 비해서 성능이 느리다.

본문 사용 파이썬 코드 요약

사용된 라이브러리
import scipy, pandas as pd
from sklearn.decomposition import PCA, TruncatedSVD, NMF

이미지 읽고 쓰고 보이기
scipy.misc.imread(파일이름)
scipy.misc.imsave(파일이름, 행렬)
scipy.misc.toimage(행렬)

이미지 읽기
scipy.misc.imread(파일이름, mode='L').reshape(45 * 40)
#이미지의 간편한 처리를 위해서 8bit 흑백 모드로 읽기

행렬 결합하기
pd.concat(결합할 행렬의 리스트, axis=1)
# axis=1 가로(열)로 합치기, 0 세로(행)로 합치기

인수분해하기
# 모델 선언, 성분 개수 지정
model = PCA(n_components=성분개수)
# 인수 분해 (압축 저장)
repo = model.fit_transform(학습 및 변형할 행렬)
# 복원 하기
final_img = model.inverse_transform(repo)
# 복원된 이미지 보기
scipy.misc.toimage(final_img)

tensorflow 접근 퀵가이드

본문은 알파고로 유명세를 타고있는 tensorflow에 대한 접근 과정에 필요한 정보들을 요약한다.
tensorflow를 편하게 사용하기 위해서 만들어진(wrapped) skflow를 통해서 tensorflow를 다루는 간략한 예제와 기존의 유명한 학습 기법과 성능을 비교해 본다.

1. skflow 소개 및 DNN 사용 예제

skflow는 파이썬의 대표적인 기계학습 라이브러리인 scikit-learn과 구글에서 공개한 딥러닝 도구 tensorflow를 조합한 라이브러리다.
익숙한 scikit-learn의 인터페이스를 통해서 tensorflow를 참조 모델 셋으로 사용하기 때문에, 기존 기계학습 사용자들이 편하게 접근 할 수 있게 도와준다.

사용 방법:
# 텐서 플로우 DNN 설정
clf = skflow.TensorFlowDNNClassifier(hidden_units=h, n_classes=n)
# 학습 데이터 입력
clf.fit(mf.train_data, mf.train_target, logdir='log_dnn')
# 실험 데이터의 실제 결과와 모델의 예측치와 비교
score = metrics.accuracy_score(mf.test_target, clf.predict(mf.test_data))
print("Accuracy: %f with TF_DDN" % score)
# 모니터링 보기
command$ tensorboard --logdir=log_dnn/2016-03-18_18-15-08
# tensorboard에서 Loss 추이 화면 (MNIST 학습 과정)
**
hidden_units은 복수개의 은닉 계층을 뜻한다.
예를 들면, [10,20]의 입력 값은 10개의 unit과 20개의 unit으로 이루어진 2개의 은닉계층을 표현한다. 최적의 값을 위한 은닉계층의 수나 유닛의 수는 실험적인 결과를 통해 유추는 것으로 보인다. (좀 더 학습이 필요한 부분이다.)

주요 알고리즘 정리

자주 사용하는 알고리즘에 대한 정의 및 개인적인 포인트를 메모한다.

심층 신경망(Deep Neural Network, DNN)
입력 계층(input layer)과 출력 계층(output layer) 사이에 복수개의 은닉 계층(hidden layer)들로 이뤄진 인공신경망(Artificial Neural Network, ANN)이다.[17][18] 심층 신경망은 일반적인 인공신경망과 마찬가지로 복잡한 비선형 관계(non-linear relationship)들을 모델링할 수 있다. 예를 들어, 사물 식별 모델을 위한 심층 신경망 구조에서는 각 객체가 이미지 기본 요소들의 계층적 구성으로 표현될 수 있다.[19] 이때, 추가 계층들은 점진적으로 모여진 하위 계층들의 특징들을 규합시킬 수 있다. 심층 신경망의 이러한 특징은, 비슷하게 수행된 인공신경망에 비해 더 적은 수의 유닛(unit, node)들 만으로도 복잡한 데이터를 모델링할 수 있게 해준다.

딥러닝 (Deep Learning)
사람의 사고방식을 컴퓨터에게 가르치는 기계학습의 한 분야이다.
과학습(OverFitting)은 항상 주의 해야할 문제이다.
하드웨어 (GPU)와 분산 처리 기술의 발전으로 다시 주목 받고 있다.
컴퓨터 비전과 같은 특정 분야에서는 압도적인 성과를 보인다.

잠재변수(Latent Variable)
직접적으로 관찰되거나 측정이 되지 않는 변수를 의미한다.
딥러닝(deep learning)의 핵심 요소이다.

이미지 처리
convolution nxm
필터 효과를 만들어낸다.
subsampling nxm
이미지 분석에서는 일반적으로 Max 값을 추출한다. (max-pooling)

인공신경망 (artificial neural network)
생물학의 신경망에서 영감을 얻은 통계학적 알고리즘이다.
시냅스의 결합으로 네트워크를 형성한 인공 뉴런(노드)이 학습을 통해 시냅스의 결합 세기를 변화시켜, 문제 해결 능력을 가지는 모델 전반을 가르킨다.

서포트 벡터 머신(support vector machine, SVM)
기계 학습의 분야 중 하나로 패턴 인식, 자료 분석을 위한 지도 학습 모델이며, 주로 분류와 회귀 분석을 위해 사용한다. 두 카테고리 중 어느 하나에 속한 데이터의 집합이 주어졌을 때, SVM 알고리즘은 주어진 데이터 집합을 바탕으로 하여 새로운 데이터가 어느 카테고리에 속할지 판단하는 비확률적 이진 선형 분류 모델을 만든다. 만들어진 분류 모델은 데이터가 사상된 공간에서 경계로 표현되는데 SVM 알고리즘은 그 중 가장 큰 폭을 가진 경계를 찾는 알고리즘이다. SVM은 선형 분류와 더불어 비선형 분류에서도 사용될 수 있다. 비선형 분류를 하기 위해서 주어진 데이터를 고차원 특징 공간으로 사상하는 작업이 필요한데, 이를 효율적으로 하기 위해 커널 트릭을 사용하기도 한다.
**
최대 마진 경계를 찾는다.
비선형의 경우 새로운 차원 공간으로의 사상작업이 필요하다.

나이브 베이지안 (Naive Bayes, NB)
기계 학습 (Machine Learning) 분야에서, 나이브 베이즈 분류 (Naïve Bayes Classification)는 특성들 사이의 독립을 가정하는 베이즈 정리를 적용한 확률 분류기의 일종으로 1950 년대 이후 광범위하게 연구되고 있다.
**
올바른 클래스가 다른 클래스 보다 확률이 높을 경우 선택된다.
조건부 확률의 독립성을 가정한 알고리즘이다.
실제 확률로 볼 수는 없지만 분류에 있어 매우 효율적이다.
자연어 처리를 비롯한 많은 영역에서 사용되고 있다.

회귀분석(回歸分析, 영어: regression analysis)
관찰된 연속형 변수들에 대해 독립변수와 종속변수 사이의 상관관계를 나타내는 선형 관계식을 구하는 기법 및 이렇게 얻은 모형의 적합도를 측정하는 분석 방법이다
회귀분석은 시간에 따라 변화하는 데이터나 어떤 영향, 가설적 실험, 인과 관계의 모델링등의 통계적 예측에 이용될 수 있다.
**
표본에서 모집단 모수를 추정하기 위한 대표적인 방법이다.
최소제곱법(최소자승법)는 근사적으로 구하려는 해와 실제 해의 오차의 제곱의 합이 최소가 되는 해를 구하는 방법이다.
최대우도법(최대가능도방법)은 어떤 모수가 주어졌을 때, 원하는 값들이 나올 가능도를 최대로 만드는 모수를 선택하는 방법이다

오차와 잔차
모수에서는 실제 값과 추정 값과의 차이를 오차라 하고,
표본에서는 통계량의 개념을 갖는 잔차라는 단어를 사용한다.

결정 트리 학습법(decision tree learning)
어떤 항목에 대한 관측값과 목표값을 연결시켜주는 예측 모델로써 결정 트리를 사용한다
신경말 알고리즘이 여러 변수를 동시에 고려하지만 결정트리는 한개의 변수를 선택한다.
**
엔트로피 계수를 통해 분기의 우선 순위를 결정한다.
지니 불순도가 0이 될때 까지 분기한다.

엔트로피(독일어: Entropie)
열역학적 계의 유용하지 않은 (일로 변환할 수 없는) 에너지의 흐름을 설명할 때 이용되는 상태 함수다. 통계역학적으로, 주어진 거시적 상태에 대응하는 미시적 상태의 수의 로그로 생각할 수 있다. 엔트로피는 일반적으로 보존되지 않고, 열역학 제2법칙에 따라 시간에 따라 증가한다.

로렌츠 곡선
경제학에서 로렌츠 곡선은 하위 x%의 가구가 y%의 소득이 분배될 때의 확률 분포를 누적 분포 함수의 그래프로 나타낸 것이다. 로렌츠 곡선은 소득 분배 정도를 나타낼 때 주로 이용된다

지니 계수(Gini coefficient, 이탈리아어: coefficiente di Gini)
소득 격차를 계수화 한 것이다. 서로 다른 로렌츠 곡선들이 교차하는 경우 비교하기가 곤란하다는 로렌츠 곡선의 단점을 보완할 수 있다. 지니 계수는 소득 분배의 불평등함 외에도, 부의 편중이나 에너지 소비에 있어서의 불평등함에도 응용된다.
인구의 누적비율과 소득의 누적 점유율 사이의 상관관계를 나타내는 로렌츠 곡선은 소득분배가 완전히 평등하다면 기울기가 1인 대각선의 형태가 될 것이다.

로지스틱 회귀(영어: logistic regression)
D.R.Cox가 1958년에 제안한 확률 모델로서 독립 변수의 선형 결합을 이용하여 사건의 발생 가능성을 예측하는데 사용되는 통계 기법이다.
흔히 로지스틱 회귀는 종속변수가 이항형 문제(즉, 유효한 범주의 개수가 두개인 경우)를 지칭할 때 사용된다.
**
플롯으로 의미 들여다 보기
X = np.arange(-20,20)
e = 2.71828182846 # 근사치
logistic = lambda x: e ** x / ( 1 + e ** x)

with xkcd():
    title('logistic function')
    plot(X,[ logistic(x) for x in X ])
    ylim([-0.1,1.1])
    #grid()
    hlines(xmin=-20,xmax=20,y=0.5,linestyle='dashed')
    vlines(ymin=0,ymax=1,x=-10,lw=167,alpha=.3,color='blue')
    vlines(ymin=0,ymax=1,x=10,lw=167,alpha=.3,color='red')
    text(s='judged 0',x=-15,y=.2,fontsize=14)
    text(s='judged 1',x=10,y=1-.2,fontsize=14)

2016년 3월 14일 월요일

파이썬 2.x 한글 에러

본문은 파이썬 버전 3.5로 작성된 코드를 2.7로 변형 할때, 간혹 생겼던 한글 문제를 해소하는 방법을 다룬다.

1. 코드에 한글이 들어 갔을 때 발생하는 문법 에러

에러 코드:
SyntaxError: Non-ASCII character …

해결 방안:
스크립트 첫번째 줄에 사용할 코드 타입을 명시해 준다.
#-*- coding: utf-8 -*-

2. 변수에 한글이 들어 갔을 때 간혹 발생하는 에러

에러코드:
UnicodeDecodeError: 'ascii' codec can't decode byte …

해결 방안:
스크립트 서두에 기본 인코딩을 지정한다.
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

**
데이터에 직접 명세할 수도 있다.
‘한글’.decode(‘UTF-8’)
or
u’한글’

**
기본 인코딩으로 python 2.x에서는 ASCII, 3.x에서는 UNICODE를 사용한다.

2016년 3월 10일 목요일

테이블 데이터 샘플링 방법

테이블에서 샘플을 추출하는 두 가지 쿼리를 다룬다.

가. ORDER BY random() LIMIT n

정확한 샘플 개수를 지정할 수 있다.
정렬(sort) 수행이 발생한다.

예상 비용
cook=> explain SELECT * FROM sample_1000 ORDER BY random() LIMIT 10;
                                 QUERY PLAN                                
----------------------------------------------------------------------------
 Limit  (cost=44.01..44.03 rows=10 width=686)
   ->  Sort  (cost=44.01..44.89 rows=352 width=686)
         Sort Key: (random())
         ->  Seq Scan on sample_1000  (cost=0.00..36.40 rows=352 width=686)
(4 rows)


나. WHERE  random() <= x (%) LIMIT n

샘플의 개수가 지정한 %를 기준으로 확률 분포를 가진다.
전체 카운트를 비교해서 적절한 샘플 x(%) 지정이 필요하다.
성능이 빠르다.

예상 비용
cook=> explain SELECT * FROM sample_1000 WHERE random() < 0.1 LIMIT 10;
                              QUERY PLAN                            
----------------------------------------------------------------------
 Limit  (cost=0.00..3.19 rows=10 width=686)
   ->  Seq Scan on sample_1000  (cost=0.00..37.28 rows=117 width=686)
         Filter: (random() < 0.1::double precision)
(3 rows)

2016년 3월 4일 금요일

파이썬 로그 관리하기

파이썬에서 기본적으로 제공하는 로깅(logging) 라이브러리의 퀵 가이드이다.

로그 이름 및 레벨을 정의 한다.
import logging
# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

핸들러를 통해서 포맷을 명시한다.
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)

응용프로그램에서 레벨에 따른 로그를 남긴다.
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')


참조

파이썬 가이드 문서
https://docs.python.org/3.5/howto/logging.html#logging-advanced-tutorial

LEVEL (명세한 레벨의 수치 보다 높을 경우 로그를 남긴다.)

MySQL 참조 가이드

본문은 MySQL 참조를 위한 메모이다.

도움말 보기
help
아이템(item) 보기
help <item>

**
포그리(postgresql)에서는  pg_hba.conf 파일에서 하는 접근 제어를
메타 테이블을 통해서 설정한다.
schema와 database를 혼용하여 사용한다.

테이블 명세서 뽑기
SELECT
    table_name '테이블이름',
    ordinal_position '속성순번',
    column_name '속성명',
    data_type '데이터타입',
    column_type '필드타입',
    column_key '키종류',
    is_nullable '널허용여부',
    extra '자동여부',
    column_default '속성기본값',
    column_comment '속성설명'
FROM
    information_schema.columns
WHERE
    table_schema = '<database>'
ORDER BY table_name , ordinal_position;

BINARY 코드 비교
binary는 blob 블럭으로 출력 됨으로, Hex 코드로 변환해서 비교하면 된다.
hex(<binary_column>)

2016년 2월 29일 월요일

웹분석 - 방문자 식별 방법

웹분석에서 방문자를 정의 한다고 할때, IP나 쿠키를 생각할 수 있다.
IP 방식은 구현이 간편하지만, IP의 유동성이나 NAT 환경에서 대표성으로 인해서 세밀하지 못하다. 일반적으로는 브라우저 단위로 세분화 가능한 쿠키 방식을 사용한다.

본문에서는 방문자 식별이 쓰이는 사례와 방법을 예시한다.

먼저 웹분석의 기본 요소를 통해서 방문자 식별 사례를 본다.

방문
최초 이벤트 발생을 시점으로 방문이 일어나고 특정 조건 하에서 방문은 유지 된다.
IDLE이 특정 시간이 지나면 방문이 끊어진 것으로 고려 할 수 있다.

방문자
쿠키에 저장된 UUID를 통해서 식별 된다.
방문 시에 식별정보가 없는 경우 UUID를 생성하고, 신규 방문자로 방문이 일어난다.
반대의 경우 재 방문자로 방문이 일어난다.

다음은 방문자 식별을 위한 UUID 생성 방법이다.

범용 고유 식별자(汎用固有識別子, 영어: universally unique identifier, UUID)는 소프트웨어 구축에 쓰이는 식별자 표준이다.
표준 형식에서 32개의 십육진수로 사용되며 8-4-4-4-12 형태와 같이 5개 그룹을 하이픈(-)으로 구분한다.

버전에 따른 생성 방식이다.
버전 1 - MAC 주소와 시간
버전 2 - DCE 보안
버전 3 - MD5 해시와 식별자이름
버전 4 - 랜덤
버전 5 - SHA-1 해시와 식별자이름

버전 4의 중복이 발생할 확률을 “생일 문제(Birthday problem)”로 계산한 예제이다.
nprobability
68,719,476,736 = 2360.0000000000000004 (4 × 10−16)
2,199,023,255,552 = 2410.0000000000005 (5 × 10−13)
70,368,744,177,664 = 2460.0000000005 (5 × 10−10)

구글 애널리틱스의 UUID는 버전 4(random)를 사용하고 있다. (가이드)
cid=35009a79-1a05-49d7-b876-2b884d0f825b

실제로 쿠키에 담긴 내용은 조금 다르다.
효율성을 위해서 randomly hash로 9자리 숫자 시간 정보 10자리 숫자를 조합한다.
예) GA1.2.699874294.1455614537
9자의 hash를 통해서 정보의 분류 용도로 활용도가 있을 것으로 보인다.

참조

생일 문제
생일 문제(生日問題)란 사람이 임의로 모였을 때 그 중에 생일이 같은 두 명이 존재할 확률을 구하는 문제이다.

n명이 있을 때의 확률
P(n) = 1 - ( 365! / ( 365**n * (365 -n)!) )
np(n)
1012%
2041%
3070%
5097%
10099.99996%
50명만 있어도 두 명의 생일이 같을 확률이 97% 이다.

위키백과
https://en.wikipedia.org/wiki/Universally_unique_identifier
https://ko.wikipedia.org/wiki/생일_문제

커버사진