2016년 2월 25일 목요일

piwik 데이터 모델 요약

오픈 소스 기반의 웹분석 도구인 PIWIK의 데이터 모델을 요약한다.

1. 데이터 생성 과정을 다룬다.
2. 테이블의 용도 및 필드명을 설명한다.
3. 테이블 명세서 시트를 기록한다.

첫번째 데이터 생성 과정이다.

가. 로그 데이터 수집 (Log Data)
나. 보관 처리 (Archiving Process)
다. 보관 데이터 생성 (Archive Data)

**
데이터 수집 대상은 4가지로 요약할 수 있다.
 - visits(방문), action types(행위), conversions(전환), ecommerce items(전자상거래)
조회 효율을 높이기 위해서 패턴 질의에 대한 보관(요약:summary) 데이터를 만든다.

2016년 2월 22일 월요일

2016년 2월 7일 일요일

전자 상거래 상품 이름 분석 II

상품 이름의 단어 조각을 트랜잭션 단위의 부분 집합(조합)으로 간주하고 연관성을 찾는 과정을 알아 본다.

본문은 자주 활용되는 연관 규칙(Association Rules)에 대한 작업 과정을 다룬다.
도구는 Python으로 전처리를 하고 분석은 R을 사용했다.

먼저 트랜잭션 데이터 소스 형태이다.

가. 장바구니 형태 (basket)
상품 이름
사각 똑딱 4P
손톱 매직 파일
헤어 집게 2P
오각 스펀지 12P
손톱 버퍼 2 세트

나. 테이블 형태 (single)
트랜잭션 단어
1 사각
1 똑딱
1
1 4P
2 손톱

두 가지 소스 중에 하나로 트랜잭션을 만든다.

가. 장바구니 형태
tr = read.transactions(“<file_name>”, format = "basket", sep=" ", rm.duplicates=TRUE)
** rm.duplicates : 트랜잭션 단위 아이탬(단어) 중복에 대한 제거 여부
     결과(return) : (중복 아이탬 수, 중복 트랜잭션 수)

나. 테이블 형태
tr = read.transactions(“<file_name>”, format = "single", sep=",", cols=c(1,2),r m.duplicates=TRUE)
** 헤더가 있는 경우 cols에 헤더 이름을 사용한다.

트랜잭션이 준비가 되었으니,

아프리오리(apriori) 알고리즘을 통해서 연관 규칙을 찾는다.

library(arules)
rules=apriori(tr, parameter=list(supp=0.01, conf=0.5))
inspect(rules)

lhs Var.2 rhs support confidence lift
1 {와이어} -> {스테인리스} 0.01001821 0.8800000 13.60901
2 {여성} -> {거실화} 0.01047359 1.0000000 54.90000
3 {거실화} -> {여성} 0.01047359 0.5750000 54.90000
4 {소스} -> {} 0.01275046 0.8000000 13.94286
5 {식탁} -> {매트} 0.01593807 1.0000000 44.81633
* lhs (Left Hand Side) - 좌변
* rhs (Right Hand Side) - 우변
* support - 지지도 = 좌우변 같이 출현한 개수 / 전제 개수
* confidence - 신뢰도 = 좌우변 같이 출한한 개수 / 좌변이 출현한 개수 = Pr(B|A)
* lift - 향상도 : 신뢰도 / 우변 지지도 = Pr(B|A) / Pr(B)

** 향상도
1을 기준으로 작으면 음의 관계 크면 양의 관계를 뜻한다.
좌우변의 지지도가 작으면서 신뢰도가 높다는 것은 좌우변의 관계가 깊다는 것을 말한다.

참고

분포 보기
library(arulesViz)
plot(rules, shading="order", control=list(main = "Words of EC Product", col=rainbow(5)))


그래프 보기
plot(rules, method="graph", control=list(type="itemsets"))

아프리오리 ( a priori )
“앞에 오는 것으로 부터”를 뜻하는 라틴어이다.
바톰 업(bottom up) 방식으로 문제에 접근 한다.
부분 집합(subset)의 빈도가 적다면 부분 집합을 포함하는 집합의 빈도도 작다는 아이디어를 활용한다.

아프리오리 in 협업적 여과 방법
http://data-rider.blogspot.kr/2016/01/blog-post_30.html

플롯(plot)에서 한글 on 맥(Mac)
par(family="AppleGothic")

코드 샘플
# 공백으로 분리된 단어를 트랜잭션 포맷으로 변경
corpus = []
tid = 0
for words in df['cleansed']:
    tid += 1
    for word in words.split():
        corpus.append((tid,word))
df = pd.DataFrame(corpus,columns=['tid','word'])

# 단어의 건수 추출
corpus = {}
for words in df['cleansed']:
    for word in words.split():
        if word not in corpus:
            corpus.setdefault(word,0)
        corpus[word] += 1
df = pd.DataFrame(list(corpus.items()),columns=['word','freq'])

# 단어의 분류 태그 달기
cmap = {
'칼라': ['블루','레드','핑크','블랙','베이지','그린','브라운','화이트','그레이'],
'사이즈': ['대','중','소'],
'재질': ['스테인리스','유리'],
'성별': ['남성','여성'],
'형태': ['원형','사각'],
'형질': ['스테인리스','유리']
}

수치 = '^(\d+\D+)+'

def flaging(word):
    for i in cmap:
        if word in cmap[i]:
            return i
    if re.match(수치,word):
        return '수치'
    return '-'

df['flag'] = df['word'].apply(flaging)

2016년 2월 5일 금요일

전자 상거래 상품 이름 분석 I

전자 상거래에 사용되는 상품 이름이 가지는 특징을 알아본다.
상품 이름은 단어(의미) 조각들로 이루어져 있고 조각들은 관계가 있을 것이다.

온라인 마켓 상품 이름을 수집한다.
상품 이름
아이스 트레이(미니)
볼메이슨 와이드 _946ML
클레어 패브릭 액자_10CMx15CM
아동용 버드 욕실화_블루
스타 미니 바스켓_3P
* 상품 이름이 친절하지 않으면 형태소 분석기를 활용하자.

상품 이름을 단어 단위로 쪼개고 태그를 부여한다.
단어
빈도
분류
단어 길이
유리 89 형질 2
세트 86 - 2
사각 86 형태 2
베이지 72 칼라 3
핑크 72 칼라 2

단어에 대한 분포이다.

빈도
단어 길이
count 1491.000000 1491.000000
mean 6.332663 3.099262
std 12.872295 1.735401
min 1.000000 1.000000
25% 1.000000 2.000000
50% 2.000000 3.000000
75% 6.000000 4.000000
max 142.000000 12.000000
* 2196 건의 상품 이름을 단어로 분리 했더니,
단어의 종류는 1491건이고 빈도는 9442 건 이었다.
* 평균 빈도와 중위 빈도의 차이를 볼 때, 일부 단어에 대한 편중이 크다.
(마치 HKR의 빈부 격차 처럼 ... )

단어 분류에 따라 흥미로운 성질들을 보인다.
분류
단어 개수
단어 빈도
빈도/개수
- 1215 6961 6
수치 258 987 4
칼라 9 764 85
사이즈 3 271 90
형질 2 231 116
형태 2 194 97
성별 2 34 17
* 상품 이름에는 상품을 분류 할 수 있는 단어들의 출현이 빈번하다.

바이그램(bi-gram)으로 빈도를 조사했다. (상위 5개)
단어 이웃
빈도
담는 아카시아 35
자주 담는 35
식탁 매트 35
원형 접시 34
동물 친구들 33

단어 바이그램에 대한 분포이다.

빈도
count 3706.000000
mean 1.955208
std 2.315853
min 1.000000
25% 1.000000
50% 1.000000
75% 2.000000
max 35.000000

빈도가 낮아서 트리그램(tri-gram) 이상은 불 필요해 보인다.
N Gram 보다는 조합 방식을 사용하면 연관성을 찾을 수 있지 않을까?

To Be Continue ...
Happy New Year 2016 with bright moon

참고

* D1 : DataFrame on Pandas Library

# 강조 컬럼에 그라디언트 적용하기
D1.style.background_gradient(cmap='magma', subset=['times'], low=1)

# 분포 명세 보기
D1.describe()

# Dict 타입 빈도 사전으로 활용하기
corpus = {}
for word in words:
    if word not in corpus:
        corpus.setdefault(word,0)
    corpus[word] += 1

# N-gram 라이브러리
from nltk.util import ngrams

# 비 문자 정규 패턴
[\W|_]+

# 수치 정규 패턴
^(\d+\D+)+

2016년 2월 4일 목요일

카이제곱 검정 실습

본문은 기 작성한 “T-Test 검정 실습”에 대한 확장된 내용을 카이제곱 검정과 함께 다룬다.

모수 검정은 표본 평균과 표본 분산을 이용하는 방법이 있다.

표본 평균의 차이를 이용하는 방법
T 분포, Z 분포
표본 분산의 차이를 이용하는 방법
F 분포, 카이제곱 분포

T-Test와 카이제곱의 공식이다.

T-TEST 공식
    ( 표본평균1 - 표본평균2 ) /  Sqrt( 표본분산1 / 표본개수1 + 표본분산2 / 표본개수2  )

카이제곱 공식
    Sum( ( 표본값 - 기대값 )**2 / 기대값 )

구현 시 주의 사항은
T-TEST 검정에서 표본분산을 구할 때는 "베셀의 수정"에 따라 표본개수에서 1개를 제외한다.
파이썬(numpy)에서는 np.var( 표본, ddof=1 )로 구할 수 있다.

핵심은
표본의 평균의 비교하는 것이 유용한가? 표본의 분산을 비교하는 것이 유용한가? 이다.
예를 들면 주사위가 잘 만들어 졌는지 검정하기 위해서 주사위를 던저서 나오는 눈금의 수를 표본으로 카이제곱 검정을 한다면 어떤가?
주사위를 60번 던졌을때 각 눈금의 기대치는 10회 이다. ( 60번 / 정6면체 )
SUM( 표본 값 (X) - 기대치 (10) )**2 / 기대치 (10) )

참고

자유도 ( Degree of Freedom, DoF)
모집단의 정보를 주는 독립적인 표본 자료의 수

DDOF (Delta Degree of Freedom, DDoF)
자유도 = 표본의 수 (N) - DDOF

베셀의 수정 ( Bessel’s Correction )
표본 관찰의 수 n이 표본 분산이나 표본 표준편차의 공식에서 n-1로 사용되는 것을 말한다.
표본의 수 n이 매우 클때는 문제가 없으나 n이 작을 때는 베셀의 수정을 통해서 모집단의 분산이나 표준편차의 추정에 발생하는 편중을 바로 잡는다.

샘플 데이터 만들기
D1 = stats.norm.rvs(loc=100,scale=1,size=50)
평균 100 편차 1인 표본 수 50개를 랜덤하게 만든다.

T-Test 함수의 사용 방법
# 표본 집단의 평균을 모집단의 평균과 비교
stats.ttest_1samp(D1, 100)
=>
( D1.mean() - 100 ) / np.sqrt(np.var(D1 - 100, ddof=1) / len(D1))
* ddof=1은 variance를 구할때, n - ddof ( n - 1) 을 뜻한다.

# 표본 집단의 비교
stats.ttest_rel(D1, D2)
=>
( D1.mean() - D2.mean() ) / np.sqrt(np.var(D1 - D2 ,ddof=1 ) / (len(D1)))

# 독립적인 표본 집단의 비교
stats.ttest_ind(D1, D2)
=>
( D1.mean() - D2.mean() ) / np.sqrt( (np.var(D1 ,ddof=1 ) / (len(D1))) + (np.var(D2 ,ddof=1 ) / (len(D2))))

카이제곱 함수의 사용방법
# D1의 평균의 분산
stats.chisquare(f_obs=D1)
=>
exp = D1.mean()
sum([ ( i - exp ) ** 2 / exp for i in D1 ])

# 표본 집단의 비교
stats.chisquare(f_obs=D1, f_exp=D2)
=>
sum(( D1 - D2 ) ** 2 / D2)

* D1, D2는 numpy의 array 타입을 사용했다.


커버 사진 (Knime)

2016년 1월 30일 토요일

블로거 활동 6개월

작년 7월 부터 본격적으로 블로거 활동을 시작했다.
데이터를 다루는 경험들을 정리하기 시작 했고,
구글 애널리틱스 연동 4인방을 통한 컨텐츠의 생산과 소비 할동 분석에 학습의 의미를 두었다.

6개월이 지난 시점에 잊고 있던 애드센스 승인이 났고 흐뭇한 마음에 소회를 남긴다.

블로거는
망각 되었을 지식을 담아두는 도서관이 되었고, 급하게 경험을 찾는 은행이 되었다.
기술을 재해석하는 기쁨을 누렸고, 자신을 되돌아 보는 일기장이 되었다.
손에 쥔 수첩처럼 함께 하고, 친구처럼 늘 곁에 있다.

글은 어떻게 써야 하나 고민하던 아이는 기록을 남기는 일에 부족함을 다할 뿐이다.

블로거는 미래의 자신을 이해시키는 방법이다.


* 구글 애널리틱스 연동 4인방
애드센스, 에드워즈, 유튜브, 블로거


애드센스 승인 후 변경된 페이지