ch0nny_log

[빅데이터분석] R _ 66. 신경망 본문

빅데이터 분석(with 아이티윌)/R

[빅데이터분석] R _ 66. 신경망

chonny 2024. 7. 24. 15:53

 

복습.  회귀 분석 문제
7
#1. 데이터프레임 생성성
data<- data.frame (
  cu = c(4.5,3.0,3.5,4.8,2.9,4.2),
  rpa = c(200,150,170,220,140,210),
  reorder = c(1,-1,-1,1,-1,1))


#2. 모델 생성
library(e1071)
model <- svm(as.factor(reorder)~cu+rpa, data=data,kernel='linear')
model # Support Vectors:3

#3. 모델 평가
train_predict <- predict(model,data)
accuracy <- sum(train_predict==data$reorder)/nrow(data)
accuracy #100%

#4. 모델 예측
new_data <- data.frame(cu=c(3.7,4.0),
                       rpa=c(180,190))
new_prediction <- predict(model,new_data)
new_prediction​

- customer satisfaction:3.7, recent purchase amount:180 : 예측값 reorder:-1 (구매x)
- customer satisfaction:4.0, recent purchase amount:190 : 예측값 reorder: 1 (재구매)

 

 

 

 

필기체 숫자 & 이미지를 숫자로 변환하면?

 

 

 

신경망 앞층의 역활과 뒷층의 역할?

앞쪽 층에서는 다양한 저수준 특징(색상, 모양 등)을 추출하고,
뒤쪽 층으로 갈수록 추상화된 고수준 특징(개념, 의미 등)을 추출합니다.

저수준 특징은 더 많은 뉴런이 필요하며, 고수준 특징으로 갈수록
정보가 압축되어 뉴런 수가 줄어듭니다.

 

 

■  수지와 설현 사진을 신경망에 입력

- 은닉 1층 - 하이퍼 파라미터 값(뉴런의 갯수를 임의로 정함)- 시그모이드 함수가 붙어있음

 

■  사과사진을 신경망에 입력하면?

"사과" 이미지를 학습한 신경망은 "빨간색"과 "둥근 모양" 등의 특징을 결합하여 "사과"라는 개념을 추출할 수 있지만, 다른 데이터로 학습된 신경망은 "사과"를 전혀 다른 방식으로 이해할 수도 있습니다.
 
은닉 1층: 저수준(색깔 모양 추론) / 은닉 2층: 고수준(개념, 의미)
따라서 신경망이 추상적인 개념을 학습하고 이해하는 과정은 여전히 연구 주제이며, 인간의 추상화 능력과는 차이가 있을 수 있습니다.

 

 

 

 

 

- 같으면 false, 다르면 true

-  비선형으로 분류(직선x , 곡선o)

- 단층으로 헤결 못하는 것을 다층으로 해결함.

 


정답: ( 62 62)

 

 



■  sigmoid 함수 만들기 

sigmoid 가  그리스어의 시그마라는 단어에서 유래를 했는데 시그마라는 단어가 영어로 S 입니다.   
S 자 모양의 함수라고 해서 시그모이드라는 이름을 붙였습니다.  

0~1 사이의 데이터를 출력하므로 확률 처럼 숫자값을 출력할 수 있어서 순전파일 때 유용하고 역전파할때는 기울기가 필요한데 기울기를 구할때미분을 하는데 S 자 모양처럼 생겨서 미분이 용이합니다. 

sigmoid<- function(x) { 1/(1+exp(-x))}

sigmoid(3) #0.95
sigmoid(-3) #0.04


x_values <-seq(-10,10, by=0.1)
x_values

y_values <-sigmoid(x_values)

plot(x_values,y_values, type='l', col='red')​

■  softmax 함수 만들기 

softmax함수의 의미는 그냥 최대값을 출력하는 max가아니라 좀 부드러운 최대값을 출력한다는 의미로 soft함수로 이름을 지었습니다.


- 입력값 (98,73)  ---> softmax ---> ( 0.8, 0.2 )
- 입력값 (98,73)  ---> max ---> ( 1, 0 )

신경망 끝에 출력측에서 이 함수가 사용되면서 결론을 내주는 함수임

print( exp(0.98) / ( exp(0.98) + exp(0.73) ) )  # 0.56  뉴진스 ETA 
print( exp(0.73) / ( exp(0.98) + exp(0.73) ) )  # 0.43  뉴진스 hypo

softmax <- function(x) {
  exp_x <- exp( x - max(x) )  # 너무 큰값이 들어오면
  exp_x / sum(exp_x)           # 계산이 안되서 빼줌
}
values <- c(2, 1)
softmax( values )   #  0.7310586 0.2689414​

■  3층 신경망

# 입력 벡터
x<- c(1,2)

# 첫번째 은닉층의 가중치
W1 <- matrix(c(1,3,5,2,4,6), nrow=2, ncol=3, byrow=TRUE)

# 첫번째 은닉층의 출력
h1 <- x%*% W1
print(h1) # (5   11   17)

# 두번째 은닉층의 가중치
W2 <- matrix(c(3,4,5,6,7,8),nrow = 3, ncol=2, byrow=TRUE)

# 두번째 은닉층의  출력
z2 <- h1%*% W2
print(z2) # (189 222)

# 세번째 출력층의 가중치
W3 <- matrix(c(0.4,0.2,0.3,0.2),nrow = 2, ncol=2, byrow=TRUE)

# 세번째 출력층의  출력
z3 <- z2%*% W3
print(z3) # (142.2 82.2)

 
## sigmoid 와 softmax 함수 기입

## sigmoid 와 softmax 함수 기입

# 입력 벡터
x<- c(1,2)

# 첫번째 은닉층의 가중치
W1 <- matrix(c(1,3,5,2,4,6), nrow=2, ncol=3, byrow=TRUE)

# 첫번째 은닉층의 출력
h1 <- sigmoid(x%*% W1)
print(h1) # (0.9933071 0.9999833    1) <- 확률

# 두번째 은닉층의 가중치
W2 <- matrix(c(3,4,5,6,7,8),nrow = 3, ncol=2, byrow=TRUE)

# 두번째 은닉층의  출력
z2 <- sigmoid(h1%*% W2)
print(z2) # (0.9999997    1)

# 세번째 출력층의 가중치
W3 <- matrix(c(0.4,0.2,0.3,0.2),nrow = 2, ncol=2, byrow=TRUE)

# 세번째 출력층의  출력
z3 <- softmax(z2%*% W3)
print(z3) # (0.5744425 0.4255575)

 

 

실습1. R을 이용해서 와인을 분류하는 신경망 만들기
#1. 데이터 불러오기
wine<-read.csv('c:\\data\\wine2.csv',stringsAsFactors = T)
head(wine)
unique(wine$Type)

#2. 결측치 확인하기
colSums(is.na(wine)) # 결측치 없음

#3. 정규화하기기
normalize <- function(x) {
  return((x - min(x)) / (max(x) - min(x)))}

wine_n <- as.data.frame(lapply(wine[, -1], normalize))

summary(wine_n) #0~1까지의 값으로 정규화가 되었음

wine2<-cbind(Type=wine$Type,wine_n)
wine2

#4. 훈련과 테스트 분리
library(caret)
set.seed(1) # 가중치 초기값을 어느자리에서든 똑같이 하기 위해서 설정정
k <- createDataPartition(wine2$Type, p = 0.9, list = FALSE)
train_data <- wine2[k, ]
test_data <- wine2[-k, ]
nrow(train_data)   # 161
nrow(test_data)    # 16

#5. 모델 훈련
install.packages('nnet')
library(nnet)

set.seed(1)
model <-  nnet(Type ~  . , data=train_data, size=2) #은닉층에 1개, 뉴런수 2개

#6. 모델 예측
result <- predict( model, test_data[  , -1], type="class")
## type='class'로 두면 t1,t2,t3 의 종속변수르 출력하고 
## type='raw'로 두면 확률을 나타냄

#7. 모델 평가
sum( result == test_data[  , 1] ) / length( test_data[  , 1] )  #1

#8.모델 성능 높이기

model2 <-  nnet(Type ~., data=train_data, size=5) # 은닉층의 뉴런수를 5개
result2 <- predict( model2, test_data[  , -1], type="class")

sum( result2 == test_data[  , 1] ) / length( test_data[  , 1] )​

 

실습2. R을 이용해서 iris을 분류하는 신경망 만들기
#1. 데이터 불러오기
iris<-read.csv('c:\\data\\iris2.csv',stringsAsFactors = T)
head(iris)
unique(iris$Species)

#2. 결측치 확인하기
colSums(is.na(iris)) # 결측치 없음

#3. 정규화하기기
normalize <- function(x) {
  return((x - min(x)) / (max(x) - min(x)))}

iris_n <- as.data.frame(lapply(iris[, -5], normalize))

summary(iris_n) #0~1까지의 값으로 정규화가 되었음

iris2<-cbind(Species=iris$Species,iris_n)
iris2

#4. 훈련과 테스트 분리
library(caret)
set.seed(1) # 가중치 초기값을 어느자리에서든 똑같이 하기 위해서 설정정
k <- createDataPartition(iris2$Species, p = 0.9, list = FALSE)
train_data <- iris2[k, ]
test_data <- iris2[-k, ]
nrow(train_data)   # 135
nrow(test_data)    # 15
#5. 모델 훈련
install.packages('nnet')
library(nnet)

set.seed(1)
model <-  nnet(Species ~  . , data=train_data, size=2) #은닉층에 1개, 뉴런수 2개


#6. 모델 예측
result <- predict( model, test_data[  , -1], type="class")

## type='class'로 두면  Iris-setosa, Iris-versicolor, Iris-virginica  의 종속변수를를 출력하고 
## type='raw'로 두면 확률을 나타냄

#7. 모델 평가
sum( result == test_data[  , 1] ) / length( test_data[  , 1] )  #1​

■  수치 예측

- nnet 패키지는 은닉층은 무조건 1개여야하고 뉴런수만 늘릴 수 있었습니다.
- neuralnet  패키지를 이용하면 층수와 뉴런수를 같이 늘릴 수 있습니다. 


실습1. 콘크리트 데이터를 이용하여 강도를 예측하는 신경망을 만드시오.
# 1. 데이터를 로드합니다.
concrete <- read.csv("c:\\data\\concrete.csv")
head(concrete)

nrow(concrete)  # 1030
ncol(concrete)   # 9 

# 2. 결측치가 있는지 확인
colSums(is.na(concrete))

# 3. 데이터를 정규화 합니다. (0~1사이로 변경)
normalize <- function(x) {
  return ( (x-min(x)) / ( max(x) - min(x) )  )
}

concrete_norm <- as.data.frame( lapply( concrete, normalize) )
head(concrete_norm)
summary(concrete_norm)

# 4. 훈련 데이터와 테스트 데이터를 분리합니다.(8대2)
library(caret)
set.seed(1)
k <- createDataPartition( concrete_norm$strength, p=0.8, list=F)

train_data <- concrete_norm[ k,  ]
test_data <- concrete_norm[ -k,  ]

nrow(train_data)  # 826
nrow(test_data)   # 204

# 5. 모델을 설정 (p332)
install.packages("neuralnet")
library(neuralnet)

# 6. 훈련 데이터로 모델을 훈련시킵니다.
set.seed(1)
concrete_model <- neuralnet( formula=strength ~ cement + slag + ash + water + 
                               superplastic + coarseagg + fineagg + age,
                             data = train_data )

# 7. 신경망을 시각화합니다.

plot(concrete_model)

# 8. 테스트 데이터를 예측
result <- compute( concrete_model,  test_data[   , 1:8] )  
result$net.result

# 9. 모델 성능 평가

cor( result$net.result,  test_data[  , 9] ) #0.8246728

 

# 10. 모델 성능 개선 (층수를 늘리기)
set.seed(1)
concrete_model <- neuralnet( formula=strength ~ cement + slag + ash + water + 
                               superplastic + coarseagg + fineagg + age,
                             data = train_data, hidden=c(5,2)  )
## hidden = c(5,2) -> 5는 은닉 1층의 뉴런수, 2는 은닉2층의 뉴런수

# 11. 신경망을 시각화합니다. (3층 신경망)

plot(concrete_model)

# 12. 테스트 데이터를 예측
result <- compute( concrete_model,  test_data[   , 1:8] ) # test data는 정답빼고
result$net.result

# 13. 모델 성능 평가

cor( result$net.result,  test_data[  , 9] ) # 0.9351368

 

  층수 은닉층의 뉴런수 상관계수 개선방법
1번실험 2층 1개 0.82  
2번실험 3층 7개 0.94 hidden =c(5,2)
3번실험 3층 11개 0.95 hidden =c(8,3)
실습1.2. 3층 신경망으로 구현하는데 하이퍼 파라미터 뉴런수의 갯수를 자동으로 늘려가며 상관계수를 확인하게 for loop 문을 완성하시오 !
for  ( i  in  5:10) {
  for ( j  in  1:3) { 
    set.seed(1)
    concrete_model <- neuralnet( formula=strength ~ cement + slag + ash + water + 
                                   superplastic + coarseagg + fineagg + age,
                                 data = train_data, hidden=c( i, j )  )
    result <- compute( concrete_model,  test_data[   , 1:8] )  
    a <- cor( result$net.result,  test_data[  , 9] )
    print( paste( 'h1:' , i,  'h2:', j,  a ) ) 
  }
}​
설명: "h1: 8 h2: 3 0.95632882539551" <- 가장좋은 모델

마지막문제. 위의 표의 결과를 막대그래프로 시각화하시오. (실험, 상관계수)
# 필요한 패키지 로드
library(plotly)

# 데이터 생성
data <- data.frame(
  Experiment = c('1번 실험', '2번 실험', '3번 실험', '4번 실험', '5번 실험'),
  Correlation_Coefficient = c(0.82, 0.94, 0.96, 0.96, 0.97)
)

# 막대 그래프 생성
plot_ly(
  data, 
  x = ~Experiment, 
  y = ~Correlation_Coefficient, 
  type = 'bar', 
  marker = list(color = c("#BBDEFB", "#FFCCBC", "#E8F5E9", "#FFF9C4", "#FCE4EC"))
) %>%
  layout(
    title = 'Correlation Coefficient by Experiment',
    xaxis = list(title = 'Experiment'),
    yaxis = list(title = 'Correlation Coefficient', range = c(0, 1)),
    showlegend = FALSE
  )