concrete.csv
0.04MB

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 신경망을 이용하여 콘크리트 강도 예측하기
concrete <- read.csv('c:/data/concrete.csv')
 
# 예측하고자 하는 결과가 정규분포를 띄는지 확인한다.
# 만약 정규분포를 띈다면 예측 결과가 좋게 나올 수 있다는 것을 알 수 있다.
hist(concrete$strength)
 
# 결측치 확인
colSums(is.na(concrete))
 
# 정규화 함수
normalize <- function(x) {
  return ( (x-min(x)) / (max(x) - min(x) ) )
}
 
# 데이터 정규화하기
concrete_norm <- as.data.frame(lapply(concrete,normalize))
 
# 0~1 사이로 데이터가 바꼈는지 확인
summary(concrete_norm$strength)
# 기존 데이터와 비교
summary(concrete$strength)
 
# train(75%) / test(27%)
nrow(concrete_norm) * 0.75 # 772.5
concrete_train <- concrete_norm[1:773, ]
concrete_test <- concrete_norm[774:1030, ]
 
# 신경망 패키지 설치
install.packages("neuralnet")
library(neuralnet)
 
# 모델 생성
concrete_model <- neuralnet(formula=strength ~ cement + slag + ash +water +superplastic + coarseagg + fineagg + age,
                            data =concrete_train)
 
# 신경망 모델 시각화
plot(concrete_model)
 
# 예측
model_results <- compute(concrete_model, concrete_test[1:8])
predicted_strength <- model_results$net.result
 
# 상관관계 확인
cor(predicted_strength, concrete_test$strength) # 0.806285848
cs

 

 

시각화

 

 

 

 

 

 

모델 성능 개선

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 모델 성능 개선 은닉층(hidden) 생성
concrete_model2 <- neuralnet(formula=strength ~ cement + slag + ash +
                               water +superplastic + coarseagg + fineagg + age,
                             data =concrete_train , hidden=c(5,2))
 
# 은닉층을 설정해 생성한 신경망 모델 시각화
plot(concrete_model2)
 
# 예측
model_results <- compute(concrete_model2, concrete_test[1:8])
predicted_strength2 <- model_results$net.result
 
# 상관관계 확인
cor(predicted_strength2, concrete_test$strength)
cs

 

hidden=c(5,2) 첫번째 은닉층 5개 / 두번째 은닉층 2개

 

 

 

 

 

다층퍼셉트론

다층 퍼셉트론

 

위의 이미지를 보자. 앞에서 설명했던 기본적인 퍼셉트론이 여러개의 층으로 이루어지는 것을 다층 퍼셉트론이라고 한다. Input은 입력층, Hidden은 은닉층, Output은 출력층으로 표현한다. 여기서 은닉층(Hidden)이 여러개를 갖게 되는 것을 다층 퍼셉트론이라고 할 수 있다.

 

 

 

model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

 

위의 코드는 다층퍼셉트론을 만드는 기본적인 코드이다. 그런데 저 코드에서 activation에 있는 relu와 sigmoid는 도대체 뭘까? 우리는 이것들을 활성화 함수라고 한다.

 

 

 

 

 

활성화 함수

 

위의 그림은 신경망을 나타내는 그림이다. 여기서 활성화 함수에 해당하는 것은 계단함수이다. 계단함수라는 것은 특정 임계값을 넘기면 활성화되는, 즉 0과 1로 출력되는 함수를 의미한다.

 

더보기
import matplotlib.pylab as plt
import numpy as np

def step_function(x) :
    result = x > 0
    return result.astype(np.int)

x = np.arange(-5,5,0.1)
y = step_function(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()

파이썬으로 구현한 계단함수

 

하지만 단층퍼셉트론이 아니라 다층퍼셉트론 같은 경우는 활성화 함수로 계단함수를 쓸 수 있을까? 어떤 기준으로 0과 1을 나눠야 하는걸까? 그것에 대한 해답이 sigmoid와 relu이다.

 

 

 

활성화 함수

 

 

 

 

 


 

 

 

 

 

  Sigmoid

더보기
import matplotlib.pylab as plt
import numpy as np

def sigmoid(x) :
    return 1/(1+np.exp(-x))

x = np.array([-1,1,2])
sigmoid(x)

x = np.arange(-5,5,0.1)
y = sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()

파이썬으로 구현한 Sigmoid함수

 

위의 그래프에 대해서는 내가 이전에 맥락을 풀어 설명했으니 참고하길 바란다. 하지만 귀찮은 사람들을 위해 간략하게 말하자면 그래프 그대로 데이터를 0과 1로 분류한다는 뜻이다. 이것이 Sigmoid 함수이다. 앞서 말했지만 퍼셉트론은 인간의 뉴런을 모델로 했기 때문에 다층 퍼셉트론같은 경우 데이터를 0과 1로 구분하여 역치 이상(1)일 경우 데이터를 다음 퍼셉트론으로 넘기는 방식으로 운영되어진다. 그런데 이쯤 되면 궁금증이 생긴다. 계단함수나 Sigmoid나 둘 다 0 또는 1 혹은 0~1 사이의 값으로 데이터를 변환해준다는 것이다. 그런데 왜 단층퍼셉트론에는 계단함수를 쓰고 다층퍼셉트론에서는 Sigmoid 또는 ReLU를 사용하는 것일까?

 

다층 퍼셉트론은 여러개의 은닉층을 보유하고 앞에서 가공되어진 데이터들이 다음 은닉층으로 넘어가는 구조이다. 계단함수를 다층 퍼셉트론에서 사용한다면 우리는 이전 데이터를 오직 0과 1, 즉 극단적인 형태로밖에 받을 수 없고 이런식이라면 다층 퍼셉트론을 만들어 좋은 모델을 만들 수 없게 된다. 하지만 Sigmoid 함수같은 경우는 값을 0~1 사이로 만들어주기 때문에 가공된 데이터를 다음 은닉층으로 보내줘도 극단적인 형태가 아니고 신경망이 데이터를 섬세하게 분류할 수 있도록 도와준다.

 

좋다. 계단함수보다 Sigmoid를 사용하는 이유를 이제는 충분히 이해했다. 그런데 ReLU는 또 왜 필요한걸까?

 

 

ReLU

더보기
import matplotlib.pylab as plt
import numpy as np

def relu(x) :
    return np.maximum(0,x)

x = np.arange(-5,5,0.1)
y = relu(x)

plt.plot(x,y)
plt.ylim(-0.5,5.5,0.1)
plt.show()

파이썬으로 구현한 ReLU함수

 

ReLU함수는 Sigmoid 단점을 해결하기 위해 나왔다. Sigmoid 함수의 단점은 0과 1사이의 데이터로 이루어져 있어 역전파를 할수록, 즉 층이 깊어질수록 활성화 값들이 0과 1에 치우쳐져 있어 미분값이 0에 가까워진다는 것이다. 이것을 Vanishing Gradient Problem(기울기 값이 사라지는 문제)이라고 한다. 즉, 전파가 역전파될 기울기 소실로 인해서 앞층까지 전파가 안된다는 이야기다. 따라서 이와 같은 문제점을 해결하고자 ReLU 함수를 사용하게 된 것이다.

 

ReLU는 0보다 작은 값에 대해서는 0을 반환하고, 0보다 큰 값에 대해서는 그 값을 그대로 반환하여 층이 깊어져도 0으로 수렴하는 오류를 범하지 않게 된다.

 

 

더 자세한 내용은 블로그를 참고하길 바란다.

 

 

+

 

 

Leaky ReLU

더보기
def leaky_relu(x) :
    return np.maximum(0.01*x,x)

x = np.arange(-20,5,0.1)
y = leaky_relu(x)

plt.plot(x,y)
plt.grid()
plt.ylim(-0.5,5.5,0.1)
plt.show()

 

파이썬으로 구현한 Leaky ReLU

 

ReLU와 동일하나 x가 음수일때 기울기(gradient)가 0.01이다.

 

 

ELU (Exponential Linear Units)

ELU 식

ELU 또한 ReLU와 비슷하나 기울기가 살아남는다는 특징이 있다.

 

 

 

'인공지능 > 인공지능 이론' 카테고리의 다른 글

16. 배치(Batch), 미니배치 학습, 에폭(Epoch), SGD  (3) 2020.08.04
15. 항등함수와 Softmax 함수  (2) 2020.08.03
13. Perceptron (퍼셉트론)  (0) 2019.09.14
12. Clustering  (0) 2019.09.13
11. 차원의 저주 / PCA  (0) 2019.09.13

 

 

 

test_vif1.csv
0.00MB
test_vif2.csv
0.00MB

 

 

 

※ 전공자가 아니기 때문에 비약적인 부분이 많을 수도 있겠으나,

대략적인 흐름을 설명하고자 하는 노력이니 전공자분들이 hoxy나 이 글을 보고 오류를 찾는다면 알려주시길 바람.

 

 

회귀분석에서 검정이 필요한 이유

우리가 회귀분석을 하는 이유가 애초에 무엇인지 생각해보자. 우리는 일정한 패턴을 갖는 데이터들로 하여금 (선형적인) 식을 만들어 그와 비슷한 데이터를 새롭게 입력받은 경우에도 문제를 해결, 혹은 예측하고자 회귀분석을 한다. 위의 데이터들을 이용하여 다음과 같은 함수를 R에서 구현해보자.

 

 

test_vif1

1
2
3
4
5
6
7
8
9
10
11
12
13
library(car) # vif 함수용
test <- read.csv('c:/data/test_vif1.csv')
test
 
# test에 있는 학생정보는 불필요하므로 제외
test <- test[-1]
 
# 회귀 모델 생성
regression_model <- lm(test$시험점수~.,data=test)
summary(regression_model)
 
# 팽창계수 확인
vif(regression_model)
cs

 

회귀 모델 요약

 

test_vif1은 시험점수, 아이큐, 공부시간에 대한 컬럼이 존재하는 데이터로 다중회귀분석에 해당하는 데이터이다. 종속변수(Y), 즉 (예측)결과인 시험점수는 독립변수(X)인 아이큐와 공부시간에 의해 나타낼 수 있다. 내가 방금 한 말을 요약하자면 아이큐와 공부시간에 의해 시험점수를 나타낼 수 있다는 것이다. 그런데 왜 굳이 회귀식을 만들어 놓고선 summary를 하고 그것을 굳이굳이 캡쳐까지 해서 올려놓은것일까? 그것에 대해 이제부터 설명하도록 하겠다. 우선 위의 그림에서 Coefficients(계수) 테이블 중 t value와 Pr(>|t|) 를 보자.

 

 

우리가 t-value와 p-value(Pr(>|t|)의 값을 보는 이유는, 이 독립변수들이 정말 회귀식을 구성하는데 필요한지에 대해 보기 위해서이다. 그리고 t-value와 p-value를 이해하기 위해서는 귀무가설과 대립가설에 대해 이해할 필요가 있다. 더 디테일한 내용에 대해서는 구글링(크흡 비전공자라 미안해...)을 하길 바란다.

 

 

 

 

 


 

 

 

 

다중 회귀식

 

 

t value : 잔차를 표준편차로 나눈값

t value의 귀무가설은 α_i(회귀계수) = 0 이다. 즉, 귀무가설을 만족한다는 것은 회귀계수 = 0 을 만족하는 것이고 이 말은 즉슨, 주어진 데이터인 X가 종속변수(Y)에 영향을 미치지 않는다는 것을 의미한다. 결국에는 쓸모 없는 데이터란 말이다. t value를 구하는 방법은 구글링을 통해 찾아보는 것을 추천한다.

 

 

Pr(>|t|) : p value

Pr(>|t|)는 p value를 의미하고 p value는 위에 구한 t value값을 기준에 해당하는 값(|t|)과 비교하여 나타낸 값으로, 이 값은 유의수준에 적합하면 할수록, 즉 0.05보다 작고 0에 가까울수록 매우 유의미한 데이터라고 인식하고 0.05보다 크면 불필요한 데이터에 가깝다고 인식한다. 위의 summary를 보면 p value 값 옆에 * 표시들이 있는데 *이 많을수록 유의미한 데이터임을 나타낸다.

 

 

 

이렇게 t value와 p value를 통해 1차적으로 독립변수가 회귀식에 필요한지 아닌지를 우선적으로 판단한다.

test_vif1 데이터에서 아이큐와 공부시간은 귀무가설을 기각하기 때문에 회귀식에 필요한 독립변수임을 알 수 있다.

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

test_vif2

1
2
3
4
5
6
7
8
9
10
11
12
13
library(car) # vif 함수용
test <- read.csv('c:/data/test_vif2.csv')
test
 
# test에 있는 학생정보는 불필요하므로 제외
test <- test[-1]
 
# 회귀 모델 생성
regression_model <- lm(test$시험점수~.,data=test)
summary(regression_model)
 
# 팽창계수 확인
vif(regression_model)
cs

 

회귀 모델 요약

 

위의 test_vif1와 같은 방식으로 회귀 모델을 요약해보았다. test_vif2의 컬럼에는 등급평균이 추가되었다. 위의 summary를 보면 아이큐와 등급평균의 p value 값이 유의수준 0.05보다 크다는 것을 알 수 있다. 이것은 결론적으로 회귀식에서 아이큐와 등급평균이 유의미하지 않다는 것을 의미한다. 어떻게 이런 일이 생긴걸까? 등급평균 하나만 추가한건데 말이다!

 

이러한 경우, 아이큐와 등급평균 두 개의 데이터는 불필요해진다. 하지만 정말 과연 그럴까? 어떻게 아이큐와 공부시간만 있을 때는 2개의 독립변수로 나타내지는 다중회귀식이 만들어지는데 지금과 같은 경우는 오직 공부시간에만 영향을 받는 단순선형회귀식이 되어버린걸까? 또한 단순선형회귀식이 된다면 이전의 회귀모델보다 데이터의 정확도가 떨어지게 될 것이다. (아니 어떻게 모은 데이터인데 안 모으니만 못하다니 이게 뭔소리야!!!!)

 

이러한 경우를 위해 우리는 팽창계수를 확인한다.

 

 

 

팽창계수(vif)

 

팽창계수 확인

 

위의 팽창계수를 보자. 아이큐와 등급평균이 22, 19로 매우 높은 값을 나타낸다는 것을 알 수 있다. 이렇게 팽창계수가 높다는 것은 다중공선성이 있다는 뜻이고, 다중공선성이 있다함은 독립변수들 중에 서로 영향을 주는 것이 있다는 뜻이다. 서로 영향을 주는데 그게 어떻게 독립변수겠는가? 따라서 우리는 서로 영향을 주는 변수들 중 하나만을 남겨 독립변수로서의 성능을 할 수 있도록 해줘야한다. 팽창계수를 확인하여 독립변수인지 아닌지를 판단하는 방법에 대해서, 현업 기준으로는 팽창계수가 보통 10보다 큰 것을 골라내고, 엄격하게는 5보다 큰 것, 느슨하게는 15~20보다 큰 것을 골라낸다.

 

위의 데이터에서는 아이큐와 등급평균이 기준 이상이므로 둘 중 하나만을 지워야 한다. 어떤 변수를 지워야할까?

결론은 팽창계수가 큰 것부터 없애야한다 이다. 현재 test_vif2의 데이터 같은 경우는 컬럼이 고작 3개 뿐이기 때문에 팽창계수가 큰 아이큐와 등급평균이 서로 영향을 준다는 것을 알 수 있다. 하지만 만약 컬럼이 30개라면? 그 이상이라면? 팽창계수가 큰 것이 10개 이상이라면? 우리는 어떤 컬럼들이 서로에게 영향을 주는지 알 수 없다. 그렇기 때문에 우선적으로 팽창계수가 가장 큰 컬럼부터 지워나가며 다시 회귀모델을 만들고, 또 거기서 팽창계수가 큰 것을 지워나가는 것을 반복하며 회귀모델을 만들어가야 한다.

 

+) 전공생분과의 대화를 통해서 알게 된 사실은 팽창계수 뿐만 아니라 상관관계로도 판단할 수 있다! 다만 상관관계로 판단하기에는 컬럼이 너무 많아서 눈에 쉽게 안 들어오니까 쉬운게 좋은 나는 대체로 팽창계수가 큰 것부터 없애는 방향으로 하려고 했는데, 노력을 조금 더 해서 정확도를 높이고자 하면 상관관계가 있는 변수들을 파악하여 그 중에서 종속변수와 연관성이 더 높은 변수를 살리는 것이 좋다. 이것은 개인의 판단이자 몫이니 참고하길 바란다!

 

 

 

 

 

 


 

 

 

 

 

결론

정확도가 높은 회귀 모델을 만들기 위해서는

1. p value로 독립변수(컬럼)가 회귀식에 필요한지 아닌지를 우선적으로 판단

2. 만약 p value에서 귀무가설을 기각하지 않는다면 팽창계수(vif)를 확인하여 다중공선성이 있는 독립변수(컬럼)를 하나씩 지워나감

     OR 상관계수로 파악하여 서로 영향을 주는 변수를 파악하고, Y(종속변수)와 상관관계가 비교적 작은 독립변수를 하나씩 지워나감

 

 

 

 

 

 

 

 

 

Netflix Movies and TV Shows

Movies and TV Shows listings on Netflix

www.kaggle.com

 

 

 

넷플릭스 데이터는 어떻게 구성되어 있는가?

더보기
# Anaconda Prompt (anaconda3) : pip install  plotly

import plotly.graph_objects as go
from plotly.offline import init_notebook_mode, iplot
import pandas as pd
from plotly.subplots import make_subplots

df = pd.read_csv("c:/data/netflix_titles.csv")
df

 

 

 

 

 

넷플릭스에 있는 TV Show와 영화 비율

더보기
# September 9, 2019 형식을 모두 숫자 형식으로 변환해줌
df["date_added"] = pd.to_datetime(df['date_added'])

# type : 영화 / TV Show
col = 'type'
grouped = df[col].value_counts().reset_index()
grouped = grouped.rename(columns={col:"count","index":col})

# plot
trace = go.Pie(labels=grouped[col], values=grouped['count'], pull=[0.05,0],marker=dict(colors=['brown','cornflowerblue']))
layout = go.Layout(title=" ",height=400,legend=dict(x=0.1,y=1.1))
fig = go.Figure(data = [trace],layout=layout)
iplot(fig)

영화가 거의 70% TV가 30%

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

넷플릭스 컨텐츠 추가 추세 (선 그래프)

더보기
d1 = df[df["type"]=="TV Show"]
d2 = df[df["type"]=="Movie"]

# 년도만 사용
vc1 = d1["date_added"].dt.year.value_counts().reset_index()
vc1.columns = ['year','count']
vc1['percent'] = vc1['count'].apply(lambda x : 100*x/sum(vc1['count']))
vc1 = vc1.sort_values('year')

vc2 = d2["date_added"].dt.year.value_counts().reset_index()
vc2.columns = ['year','count']
vc2['percent'] = vc2['count'].apply(lambda x : 100*x/sum(vc2['count']))
vc2 = vc2.sort_values('year')

trace1 = go.Scatter(x=vc1['year'], y=vc1["count"],name="TV Shows",marker=dict(color='cornflowerblue'))
trace2 = go.Scatter(x=vc2['year'], y=vc2['count'],name="Movie",marker=dict(color='brown'))
data = [trace1,trace2]

layout = go.Layout(title="넷플릭스 컨텐츠 추가 증가 추세",legend=dict(x=0.1,y=1.1,orientation="h"))
fig = go.Figure(data,layout=layout)
fig.show()

20년도는... 데이터가 얼마 없으니.. 무시하고... 계속 증가하는 추세다.. 이말입니다...

 

 

 

 

 

 

넷플릭스 컨텐츠 추가 추세 (막대 그래프)

더보기
vc1 = d1["date_added"].dt.year.value_counts().reset_index()
vc1.columns = ['year','count']
vc1['percent'] = vc1['count'].apply(lambda x : 100*x/sum(vc1['count']))
vc1 = vc1.sort_values('year')

vc2 = d2["date_added"].dt.year.value_counts().reset_index()
vc2.columns = ['year','count']
vc2['percent'] = vc2['count'].apply(lambda x : 100*x/sum(vc2['count']))
vc2 = vc2.sort_values('year')

bar1 = go.Bar(x=vc1['year'],y=vc1['count'],name="TV Shows",marker=dict(color='cornflowerblue'))
bar2 = go.Bar(x=vc2['year'],y=vc2['count'],name='Movies',marker=dict(color='brown'))

data = [bar1,bar2]

layout = go.Layout(title="막대그래프로 보는 넷플릭스 컨텐츠 추가 증가 추세", legend=dict(x=0.1,y=1.1,orientation="h"))
fig = go.Figure(data,layout=layout)
fig.show()

점점 증가하고 있군요... 넷플릭스 힘 줘!!!! 나 넘 즐겁게 보고 있다고~! 모던 패밀리 마지막 시즌 언제 올려줄거야ㅠ

 

 

 

 

 

 

넷플릭스 컨텐츠 추가 추세 (PIE 그래프)

더보기
df['year_added'] = df['date_added'].dt.year
k = round(df.groupby('year_added')['type'].value_counts(normalize=True)*100)
print(k)
k.reset_index(name='percent(%)')

d1 = df[df["type"]=="TV Show"]
d2 = df[df["type"]=="Movie"]
date = d1['date_added'].dt.year.value_counts().reset_index()
date2 = d2['date_added'].dt.year.value_counts().reset_index()

result = pd.merge(date,date2,how='outer',on='index').sort_values(by=['index'],ascending=False)
result.columns = ['year','TV Show','Movie']
result.index=[i for i in range(len(result))]

result
data0 = {"values" : (result["TV Show"][0],result["Movie"][0]),
         "labels" : ("TV Show","Movie"),
         "domain" : {"row" : 0 , "column" : 0},
         "name" : result["year"][0],
         "hoverinfo" : "label+value+name",
         "hole" : .4,
         "type" : "pie"
        }

data1 = {"values" : (result["TV Show"][1],result["Movie"][1]),
         "labels" : ("TV Show","Movie"),
         "domain" : {"row" : 1 , "column" : 0},
         "name" : result["year"][1],
         "hoverinfo" : "label+value+name",
         "hole" : .4,
         "type" : "pie"
        }

data2 = {"values" : (result["TV Show"][2],result["Movie"][2]),
         "labels" : ("TV Show","Movie"),
         "domain" : {"row" : 2 , "column" : 0},
         "name" : result["year"][2],
         "hoverinfo" : "label+value+name",
         "hole" : .4,
         "type" : "pie"
        }

data3 = {"values" : (result["TV Show"][3],result["Movie"][3]),
         "labels" : ("TV Show","Movie"),
         "domain" : {"row" : 0 , "column" : 1},
         "name" : result["year"][3],
         "hoverinfo" : "label+value+name",
         "hole" : .4,
         "type" : "pie"
        }

data4 = {"values" : (result["TV Show"][4],result["Movie"][4]),
         "labels" : ("TV Show","Movie"),
         "domain" : {"row" : 1 , "column" : 1},
         "name" : result["year"][4],
         "hoverinfo" : "label+value+name",
         "hole" : .4,
         "type" : "pie"
        }

data5 = {"values" : (result["TV Show"][5],result["Movie"][5]),
         "labels" : ("TV Show","Movie"),
         "domain" : {"row" : 2 , "column" : 1},
         "name" : result["year"][5],
         "hoverinfo" : "label+value+name",
         "hole" : .4,
         "type" : "pie"
        }


data = [data0,data1,data2,data3,data4,data5]

layout = go.Layout({
    "title" : "2015~2020 type 비율 시각화",
    "grid" : {"rows" : 3, "columns" : 2}
})

fig = go.Figure(data=data,layout=layout)
iplot(fig)

압도적으로 높은 영화 추가량

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

TV Show, 영화 발매 증가 추세

더보기
vc1 = d1["release_year"].value_counts().reset_index()
vc1.columns = ['release_year','count']
# vc1['release_year'][21] = "under_1990"
# vc1['count'][21] = vc1.iloc[-21:-1,].sum()[1]
vc1 = vc1.sort_values('release_year',ascending=False)
vc1 = vc1.iloc[1:21,] # 1997년(netflix 설립일) ~ 2019년까지

vc2 = d2["release_year"].value_counts().reset_index()
vc2.columns = ['release_year','count']
vc2 = vc2.sort_values('release_year',ascending=False)
vc2 = vc2.iloc[1:21,]

bar1 = go.Bar(x=vc1['release_year'],y=vc1['count'],name="TV Shows",marker=dict(color='cornflowerblue'))
bar2 = go.Bar(x=vc2['release_year'],y=vc2['count'],name="Movies",marker=dict(color='brown'))
data = [bar1,bar2]

fig = make_subplots(rows=2, cols=1, shared_xaxes=False)
fig.add_trace(bar1,row=1,col=1)
fig.add_trace(bar2,row=2,col=1)

fig.update_layout(title_text="TV Show, 영화 발매 증가 추세")
fig.show()

영화 데이터가 2019년도에 갑자기 줄어들었다. 우연의 일치일까?

 

 

 

 

 

어떤 달에 많이 업로드될까?

더보기
tv = d1["date_added"].dt.month.value_counts().reset_index()
tv.columns = ['month','count']
tv['percent'] = tv['count'].apply(lambda x : 100*x/sum(tv['count']))
tv.sort_values('month')

movie = d2["date_added"].dt.month.value_counts().reset_index()
movie.columns = ['month','count']
movie['percent'] = movie['count'].apply(lambda x : 100*x/sum(movie['count']))
movie.sort_values('month')

trace1 = go.Bar(x=tv['month'],y=tv['count'],name='TV Shows',marker=dict(color="cornflowerblue"))
trace2 = go.Bar(x=movie['month'],y=movie['count'],name='Movies',marker=dict(color='brown'))

fig = make_subplots(rows=2, cols=1, shared_xaxes=False)
fig.add_trace(trace1,row=1,col=1)
fig.add_trace(trace2,row=2,col=1)

fig.update_layout(title_text="어떤 달에 많이 업로드될까?")
fig.show()

# + 날짜와 컨텐츠 발매는 상관성이 있는가?

겨울에 많이들 나오네...

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

관람등급 등급표

더보기
col = 'rating'

tv = d1[col].value_counts().reset_index()
tv.columns=[col,'count']
tv = tv.sort_values(col)

movie = d2[col].value_counts().reset_index()
movie.columns = [col,'count']
movie = movie.sort_values(col)

trace1 = go.Bar(x=tv[col],y=tv['count'],name='TV Shows',marker=dict(color="cornflowerblue"))
trace2 = go.Bar(x=movie[col],y=movie['count'],name='Movies',marker=dict(color='brown'))

data = [trace1,trace2]

layout = go.Layout(title="관람등급", legend=dict(x=0.1,y=1.1,orientation="h"))
fig = go.Figure(data,layout=layout)
fig.show()

영화는 압도적으로 성인물이 많다.(TV-MA : 17세 미만의 어린이나 청소년이 시청하기에 부적절한 프로그램)

TV는 그나마 비율이 적절하다. (TV-14 : 14세 미만의 어린이가 시청하기에 부적절한 프로그램)

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

장르

더보기
from collections import Counter
col = 'listed_in'

# 리스트에 저장
categories1 = ", ".join(d1[col]).split(", ")
for i in range(len(categories1)) :
    categories1[i] = categories1[i].strip("TV Shows")
    
categories2 = ", ".join(d2[col]).split(", ")

# 빈도수 측정을 위해 counter 사용
counter_list1 = Counter(categories1).most_common(50)
counter_list2 = Counter(categories2).most_common(50)

labels1 = [_[0] for _ in counter_list1][::-1]
values1 = [_[1] for _ in counter_list1][::-1]

labels2 = [_[0] for _ in counter_list2][::-1]
values2 = [_[1] for _ in counter_list2][::-1]

trace1 = go.Bar(y=labels1,x=values1,orientation='h',name="TV Shows",marker=dict(color='cornflowerblue'))
trace2 = go.Bar(y=labels2,x=values2,orientation='h',name="Movies",marker=dict(color='brown'))

data = [trace1,trace2]

fig = make_subplots(rows=2, cols=1, shared_xaxes=False)
fig.add_trace(trace1,row=1,col=1)
fig.add_trace(trace2,row=2,col=1)

fig.update_layout(title_text="TV Show, 영화 장르 파악")
fig.show()

드라마, 영화 모두 drama, 코미디가 가장 많고 TV는 범죄물이, 영화는 다큐멘터리가 그 다음으로 많다.

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

넷플릭스에 있는 영화 중 가장 많이 출연한 사람들

더보기
def country_trace(country, flag = "movie"):
    df["from_us"] = df['country'].fillna("").apply(lambda x : 1 if country.lower() in x.lower() else 0)
    small = df[df["from_us"] == 1]
    if flag == "movie":
        small = small[small["duration"] != ""]
    else:
        small = small[small["season_count"] != ""]
    cast = ", ".join(small['cast'].fillna("")).split(", ")
    tags = Counter(cast).most_common(25)
    tags = [_ for _ in tags if "" != _[0]]

    labels, values = [_[0]+"  " for _ in tags], [_[1] for _ in tags]
    trace = go.Bar(y=labels[::-1], x=values[::-1], orientation="h", name="", marker=dict(color="olivedrab"))
    return trace

from plotly.subplots import make_subplots
traces = []
titles = ["United States", "","India","", "United Kingdom", "Canada","", "Spain","", "Korea"]
for title in titles:
    if title != "":
        traces.append(country_trace(title))

fig = make_subplots(rows=2, cols=5, subplot_titles=titles)
fig.add_trace(traces[0], 1,1)
fig.add_trace(traces[1], 1,3)
fig.add_trace(traces[2], 1,5)
fig.add_trace(traces[3], 2,1)
fig.add_trace(traces[4], 2,3)
fig.add_trace(traces[5], 2,5)

fig.update_layout(title="많이 출연한 사람",height=1200, showlegend=False)
fig.show() 

한국ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 이경영 1위ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 어쉉쉉!!!!

 

 

 

 

 

넷플릭스에 있는 영화 중 가장 많은 작품이 있는 감독들

더보기
def country_trace(country, flag = "movie"):
    df["from_us"] = df['country'].fillna("").apply(lambda x : 1 if country.lower() in x.lower() else 0)
    small = df[df["from_us"] == 1]
    if flag == "movie":
        small = small[small["duration"] != ""]
    else:
        small = small[small["season_count"] != ""]
    cast = ", ".join(small['director'].fillna("")).split(", ")
    tags = Counter(cast).most_common(25)
    tags = [_ for _ in tags if "" != _[0]]

    labels, values = [_[0]+"  " for _ in tags], [_[1] for _ in tags]
    trace = go.Bar(y=labels[::-1], x=values[::-1], orientation="h", name="", marker=dict(color="#66cdaa"))
    return trace

from plotly.subplots import make_subplots
traces = []
titles = ["United States", "","India","", "United Kingdom", "Canada","", "Spain","", "Korea"]
for title in titles:
    if title != "":
        traces.append(country_trace(title))

fig = make_subplots(rows=2, cols=5, subplot_titles=titles)
fig.add_trace(traces[0], 1,1)
fig.add_trace(traces[1], 1,3)
fig.add_trace(traces[2], 1,5)
fig.add_trace(traces[3], 2,1)
fig.add_trace(traces[4], 2,3)
fig.add_trace(traces[5], 2,5)

fig.update_layout(title="이름이 많이 있는 감독",height=1200, showlegend=False)
fig.show() 

넷플릭스의 아들 봉준호... 나머지 영어 이름들은 안찾아서 모르지만 공동 감독이지 않을까..하는 마음

 

 

 

EDA_Netflix.ipynb
1.10MB

더 자세한 내용은 위의 파일로 확인하길!

 

 

 

 

 

 

 

 

 

 

 

simple_hg.csv
0.00MB
challenger.csv
0.00MB

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 탄닌(영양제) 함유량과 애벌레 성장 간의 관계
advertising <- read.csv('c:/data/simple_hg.csv',header=T)
advertising
 
plot(input~cost,data=advertising,pch=21,col='blue',bg='red')
 
regression <- lm(input~cost,data=advertising)
 
abline(regression,col='pink')
title("광고비가 매출에 미치는 영향")
 
residual <- predict(regression,cost=cost)
residual
 
join <- function(i)
  lines(c(cost[i],cost[i]),c(input[i],yhat[i]), col="black")
sapply(1:length(residual),join)
cs

 

 

 


 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 온도가 O형링 파손수에 끼치는 영향
launch <- read.csv('c:/data/challenger.csv',header=T)
names(launch)
# distress_ct : O형링 파손수
# temperature : 온도
# field_check_pressure : 압력
# flight_num : 비행기 번호
 
 
# 회귀식 만들기
<- lm(distress_ct~temperature,launch)
#     y축          x축
# = lm(formula=distress_ct~temperature,data=launch)
 
 
# launch 데이터와 회귀식 그래프에서 보이기
plot(distress_ct~temperature,data=launch,col='red',bg='red',pch=21)
abline(m,col='blue')
title("온도가 O형링 파손에 미치는 영향")
cs

 

 

 

+ Recent posts