횟수가 정해진 반복

화면에 "hello world\n"을 다섯 줄 출력=>printf 함수 다섯 번 호출

단순이 이렇게 적을 수 있지만 500번 호출하려면 500번을 그대로 다 써야하는가? 아니다.

 

반복문을 사용한다면 훨씬 편리할 것이다. 흐름도를 살펴보자.

#include <stdio.h>

int main()
{
    int count=0;
    while(count<500){
        printf("hello world\n");
        count++;
    }
    return 0;
}

    

그러나 위처럼 단순한 반복은 없다.

예) 1부터 1000까지 합 구하기.

#include <stdio.h>

int main()
{
    int count=1;
    int sum=0;
    
    while(count<=1000){
        sum+=count;
        count++;
    }
    printf("1-1000까지의 합은 : %d\n",sum);
    return 0;
}

 

while 문 내부 계산 내용 및 결과는 얼마든지 복잡할 수 있다.

예2) 짝수 홀수 별 총합 구하기.

#include <stdio.h>

int main()
{
    int start,end,temp;
    int sum=0;
    int even_sum=0;
    int odd_sum=0;
    scanf("%d %d",&start,&end);
    if(start>end){
        temp=end;
        end=start;
        start=temp;
    }
    while(start<=end){
        if((start%2)==0){
            even_sum+=start;
        }
        else if((start%2)==1){
            odd_sum+=start;
        }
        start++;
    }
    printf("even_sum=%d\n",even_sum);
    printf("odd_sum=%d\n",odd_sum);
    return 0;
}

'Computer engineering > C' 카테고리의 다른 글

반복문-for  (0) 2021.05.06
반복문-While(2)  (0) 2021.05.02
반복문-While(1)  (0) 2021.05.02
If-else 조건문  (0) 2021.04.21
If 조건문  (0) 2021.04.11

앞선 포스트 처럼 반복문은

-조건에 맞는동안 계속 반복

-횟수가 정해진 반복

이 2가지로 나눌 수 있다.

 

조건에 맞는 동안 계속 반복

예제1] -1이 입력될때까지 더한다 

=>0이상의 수만 더한다.

 

흐름도

이 흐름도에서 -1을 입력하게 된다면 빠져나오긴 하지만 한가지 문제가 생긴다. sum 단계에서 -1을 입력함과 동시에 빠져나오기 전, -1을 더하고 빠져나오게 된다.

흐름도의 문제점

이를 수정할 수 있는 방법은 무엇일까? 방법은 간단하다. 다시 -1을 빼주면 된다.

흐름도 수정본

#include <stdio.h>

int main()
{
    int sum=0;
    int input=0;
    while(input>-1){
        scanf("%d",&input);
        sum+=input;
    }
    sum-=input;
    printf("sum= %d\n",sum);
    return 0;
}

예제2] 사용자에게 계속 무언가를 할 것인지 물어보는 반복

흐름도

#include <stdio.h>
void sum_input(void){
    int sum=0;
    int input=0;
    while(input>-1){
        scanf("%d",&input);
        sum+=input;
    }
    sum-=input;
    printf("sum=%d\n",sum);
    return 0;
}


int main()
{
    int sum,cont,input;
    cont=1;
    sum,input=0;
    
    while(cont==1){
        scanf("%d",&input);
        sum+=input;
        printf("계속 더하겠습니까?(예:1, 아니오:0)");
        scanf("%d",&cont);
    }
    printf("sum=%d\n",sum);
    return 0;
}

do-while문 사용

조건에 맞는동안 계속 반복(조건검사 전 무조건 한 번은 수행)

do{} 부분이 무조건 한번 수행한 후 조건을 비교하여 계속 수행할 것인지 판단. 무조건 한 번은 실행한다.

 

#include <stdio.h>
void sum_input(void){
    int sum=0;
    int input=0;
    while(input>-1){
        scanf("%d",&input);
        sum+=input;
    }
    sum-=input;
    printf("sum=%d\n",sum);
    return 0;
}
void sum_input_qna(void){
    int sum,cont,input;
    cont=1;
    sum,input=0;
    
    while(cont==1){
        scanf("%d",&input);
        sum+=input;
        printf("계속 더하시겠습니까?(예:1, 아니오:0)");
        scanf("%d",&cont);
    }
    printf("sum=%d\n",sum);
    return 0;
}

int main()
{
    int menu;
    do{
        printf("메뉴를 입력하세요.: ");
        scanf("%d",&menu);
        if(menu!=1&&menu!=2) printf("1,2중에 입력하세요.\n");
    }while(menu!=1 &&menu!=2);
    return 0;
}

 

'Computer engineering > C' 카테고리의 다른 글

반복문-for  (0) 2021.05.06
반복문-While(3)  (0) 2021.05.03
반복문-While(1)  (0) 2021.05.02
If-else 조건문  (0) 2021.04.21
If 조건문  (0) 2021.04.11

반복구조

계속 반복해야 하는 상황

1) 조건에 맞는동안 계속 반복

 

2) 횟수가 정해진 반복

간단한 while-switch 문 예제

#include <stdio.h>
int calculator(int a, char op, int b)
{
    int result;
    switch(op){
        case '+':
            result=a+b;
            break;
        case '-':
            result=a-b;
            break;
        case '*':
            result=a*b;
            break;
        case '/':
            result=a/b;
            break;
        case '%':
            result=a%b;
            break;
        default:
            printf("잘못된 연산자를 입력했습니다.");
            return -1;
    }
}
void testCaluclator(void){
    int a, b, c;
    char op;
    printf("숫자 연사자 숫자 형식으로 입력하세요");
    scanf("%d %c %d", &a,&op,&b);
    
    c=calculator(a,op,b);
}
void testGrade(){
    int score;
    printf("input score");
    scanf("%d",&score);
    if(score>90) printf("A\n");
    else if(score >80) printf("B\n");
    else if(score>70) printf("C\n");
    else if(score>60) printf("D\n");
    else printf("F\n");
}
int leafyear(int year){
    if(((year%4==0)&&(year%100!=0))||(year%400==0))
        return 29;
    else
        return 28;
}
int daysofmonth(int month){
    int result,year;
    switch(month)
    {   if(month<1||month>12){
            printf("잘못된 입력입니다.");
            return -1;
    }
        case 2:
            printf("input year: ");
            scanf("%d",&year);
            result=leafyear(year);
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            result=30;
            break;
        default:
            result=31;
    }
    return result;
}
void testDaysofmonth()
{
    int mon;
    printf("몇일인지 알고 싶은 월을 입력하세요 : ");
    scanf("%d",&mon);
    printf("%d월은 '%d일까지 있습니다",mon,daysofmonth(mon));
}
int main()
{
    int cont=1;
    int choice=0;
    
    while(cont)
    {
        printf("input choice : ");
        scanf("%d",&choice);
        switch(choice){
            case 1:
                testCaluclator();
                break;
            case 2:
                testGrade();
                break;
            case 3:
                testDaysofmonth();
                break;
            case -1:
                cont=0;
                break;
            default:
                printf("잘못된 입력입니다.");
        }
    }
    return 0;
}

 

'Computer engineering > C' 카테고리의 다른 글

반복문-While(3)  (0) 2021.05.03
반복문-While(2)  (0) 2021.05.02
If-else 조건문  (0) 2021.04.21
If 조건문  (0) 2021.04.11
4. 대입 및 산술 연산자  (0) 2021.04.01

로지스틱 회귀(Logistic Regression)

영국의 통계학자인 D.R. Cox가 1958년에 자안한 확률 모델로서 독립 변수의 선형 결합을 이용하여 사건의 발생 가능성을 예측하는데 사용되는 통계 기법이다.

로지스틱 회귀의 목적은 일반적인 회귀 분석의 목표와 동일하게 종속변수와 독립변수간의 관계를 구체적인 함수로 나타내어 향후 예측 모델에 사용하는 것이다.

 

로지스틱 함수(Logistic Function), Odds

실제 많은 자연, 사회현상에서는 특정 변수에 대한 확률값이 선형이 아닌 S-Curve 형태를 따라는 경우가 많다.

이러한 S-Curve 함수를 표현해낸 것이 바로 로지스틱 함수이다. 

이것이 인공지능 분야에서는 시그모이드 함수라고 불린다.

 

로지스틱 함수는 x값으로 어떤 값이든 받을 수가 있지만 출력 결과는 항상 0에서 1사이 값이 된다. 즉, 확률밀도함수(Probability Density Function, PDF)요건을 충족시키는 함수다.

로지스틱 함수(Sigmoid)

승산(Odds)이란 임의의 사건 A가 발생하지 않을 확률 대비 일어날 확률의 비율을 뜻한다.

Odds

만약 사건 A가 일어날 확률 P(A)가 1에 가까워 진다면, 그 승산 값은 점점 커진다. 반대로 P(A) 가 0으로 가까워 진다면 값은 점점 작아진다는 뜻이다.

P(A)를 x축 사건, A의 승산을 y축에 놓고 그래프를 본다면 다음과 같다.

이항 로지스틱 회귀

이항 로지스틱이란 범주가 두 개인 분류 문제를 풀어야 하는 경우 사용된다. 종속 변수 Y가 연속형 숫자가 아닌 범주일 때는 기존 회귀 모델을 적용할 수 없다.

 

회귀식의 장점은 그대로 유지하되 종속변수 Y를 범주가 아닌(범주 1이 될)확률로 두고 식을 세워보자.

위 식에서 좌변의 범위는 0~1사이다. 하지만 우변은 음의 무한대에서 양의 무한대 범위를 가지기 때문에 식이 성립하지 않는 경우가 존재할 수 있다. 좌변을 Odds로 설정해보자.

좌변을 Odds로

그러나 이번에도 범위는 맞지 않는다. 좌변의 범위는 0에서 무한대의 범위를 갖는다. 이와는 다르게 우변(회귀식)은 그대로 음의 무한대에서 양의 무한대 범위이다.

 

이 과정에서 로그를 취하자. 이 결과 로그 승산의 범위는 음의 무한대에서 양의 무한대가 된다. 이렇게 함으로써 양변의 범위가 일치하게 된다. 다음은 로그승산의 그래프이다.

로그 승산 그래프

결과적으로 로지스틱 회귀 모델의 최종 식은 다음과 같다.

위 식을 입력벡터 x가 주어졌을 때 범주 1일 확률을 기준으로 정리해주면 다음과 같다.

최종 도출된 식은 곧 로지스틱 함수의 꼴과 같다.

 

이항 로지스틱 회귀의 결정경계

위와 같이 이항 로지스틱 모델에 범주 정보를 모르는 입력벡터 x를 넣으면 범주 1에 속할 확률을 반환해 준다.

그 확률값이 얼마나 되어야 범주 1로 분류할 수 있는가? 가장 간단한 방법은 다음과 같다.

범주가 두 개뿐이므로, 위 식 좌변을 p(x)로 환하면 식을 다음과 같이 정리할 수 있다.

마찬가지로  βTx<0βTx<0 이면, 해당 데이터의 범주를 0으로 분류하게 된다. 따라서, 로지스틱모델의 결정경계(decision boundry)는 βTx=0βTx=0인 하이퍼플레인(hyperplane)이다. 

입력벡터가 2차원인 경우의 시각화

다항로지스틱 회귀

범주가 세 개 이상일때 사용한다.

그러나 범주가 3개만 있다면 이항 로지스틱 모델 2개로 문제를 해결할 수 있다.

이 경우에서 모델은 2개이고 범주가 3개인데 이 관계는 다음과 같다.

K(>=3)범주를 분류하는 다항로지스틱 회귀 모델의 입력벡터 x가 각 클래스로 분류될 확률은 다음과 같다.

위 식은 다음과 같이 이해하면 가장 쉬울 것이다. k개의 범주가 생길 확률을 전부 더한것에서 k가 일어날 확률이다.

 

 

머신러닝과 로지스틱

로지스틱회귀는 결국 이항이든 다항이든 머신러닝 분류문제를 해결하는 방법 중 하나이다.

결론적으로 위 내용은 통계학적 지식을 기반으로 이해하는 방법이며, ML 분류 문제를 다룰 경우 본인이 생각하는 가장 쉬운 2가지 방법이 있다.

<파이썬>

1. 사이킷런 LogisticRegression() 모듈 사용

Parameter

-Penalty: {'l1','l2','elasticnet','none'}, default='l2'

-dual: bool, default=False

-tol: float, default=1e-4 => 정지 기준에 대한 허용오차 설정

-C: float, default=1.0 =>정규화 강도에 대한 역, 서포트벡터 머신과 마찬가지로 값이 작을수록 더 강력한 정규화 지정

-fit_intercept: bool, default=True

-intercept_scaling: float,default=1

-class_weight: dict or 'balanced', default=None

-random_state: int, RandomState instance, default=None

-solver: {'newton-cg','lbfgs','liblinear','sag','saga'}, default='lbfgs'

-max_iter: int,default=100

-multi_class: {'auto','ovr','multinomial'},default='auto'

-verbose: int,default=0

-warm_start: bool,default=False

-n_jobs: int, default=None

-l1_ratio: float,default=None

Attributes

Class_: ndarray of shape(n_classes,)

coef_: ndarray of shape(1,n_features) or (n_classes,n_features)

intercept: ndarray of shape(1,) or (n_classes,)

n_iter_: ndarray of shape(n_classes,) or (1,)

 

Methods

2. tensorflow.keras.losses.categorical_crossentropy

위 모듈은 대분류에서 위 방법만을 얘기한 것 이므로 추후에 다시한번 포스팅 하겠다. 

'Machine Learning' 카테고리의 다른 글

앙상블 학습(Ensemble Learning)  (0) 2021.04.28
Catboost  (0) 2021.04.11

앙상블(Ensemble)

*ensemble: 모두 함께, 일제히; 동시에

 

앙상블 학습은 모델 결합(model combining)이라고 부르기도 한다.

어떤 데이터의 값을 예측한다 할 때, 보통 하나의 모델을 활용한다. 하지만 여러 개의 모델을 조화롭게 학습시켜 그 모델들의 예측 결과들을 이용한다면 더 정확한 예측값을 구할 수 있을 것이다.

즉, 하나의 모델만을 학습시켜 사용하지 않고 여러 모델을 학습시켜 결합하는 방식으로 문제를 처리한다.

특히, 모델 하나로 원하는 성능을 낼 수 없을 때 앙상블 학습을 사용하면 효과적인데, 개별로 학습한 여러 개의 모델을 조합하여 일반화(generalization) 성능을 향상 시킬 수 있다.

 

여기서 개별로 학습된 모델을 weak learner라고 표현하기도 한다. 

즉, 약하게 학습된 여러 모델들을 결합하여 사용하는 것을 앙상블 학습이라 할 수 있다.

 

Ensemble classifier

앙상블 모델의 장점

위 모델을 사용함으로 써 다음 2가지 장점을 얻을 수 있다.

1. 성능을 분산시키기 때문에 과적합(overfitting) 감소 효과가 있다.

2. 개별 모델 성능이 잘 안 나올 때 앙상블 학습을 이용하면 성능이 향상될 수 있다.

 

과적합 현상을 어느 정도 막을 수 있다는 것 자체가 성능 향상이라는 말과 거의 같은 의미로 봐도 무방하다.

 

앙상블 학습의 분류

앙상블 학습은 방법론에 따라 크게 두 가지로 나누어질 수 있다.

취합

weak learner(개별 모델)들이 미리 정해져 있어 이들을 취합해 사용하는 방법.

 

종류: 다수결/투표 기반 방법, 배깅(bagging), 페이스팅(pasting), 랜덤 포레스트(random forest)

 

다수결/투표 기반 방법

다수결/투표 기반 모델

여러 모델에서 출력된 결과를 종합하여 나온 것을 최종 output으로 설정하는 방법이다.

위 모델을 해석해보면 7개의 모델이 있고 새로운 인스턴스로 1을 넣었다.

랜덤 포레스트 모델에서 최종적으로 각 모델 7개 중, 1은 5개가 나왔고 2는 2개가 나왔으므로 최종 클래스 output은 1이 된다.  

 

배깅(bagging)과 페이스팅(pasting)

bagging model and pasting model
출처:swallow.github.io

배깅과 페이스팅 모두 train set을 random sampling 하여 잘게 나눈 후 나누어진 train set을 여러 개의 모델에 할당하여 학습시킨다. 

배깅은 중복을 허용하며 train set을 나누는데 통계학에서는 이 방법을 부트스트랩, 중복이 허용된 리셈블링이라고 한다.

즉, 배깅은 전체 train set에서 여러 번 중복을 허용한 복원 추출을 한다고 생각할 수 있다.

 

이와 반대로 중복을 허용하지 않고(비복원 추출) train set을 나누는 것, 즉 부트스트랩의 반대말을 페이스팅이라고 한다.

 

랜덤 포레스트(random forest)

random forest model

여러 개의 결정트리(decision tree)를 생성하여 각각의 트리에서 나오는 결과를 취합하는 방법이다.

위 과정에서 여러 결정트리를 생성할 때 배깅과 부스팅 방법을 사용하기도한다.

 

부스팅

weak learner들을 하나씩 점진적으로 연결하여 strong learner를 만드는 방법

종류: 에이다 부스트(Ada Boost)와 그레디언트 부스트(Gradient Boost)가 있다.

 

에이다 부스트(Ada boost)와 그레디언트 부스트(Gradient boost)

Ada boost

 

Gradient boost

weak learner(개별 모델)들의 결과를 한꺼번에 취합하는 것이 아닌 결과들을 순차적으로 적용한다.

Ada boost는 각 weak learner(개별 모델)을 순차적으로 적용해 나가는 과정에서 잘 분류된 샘플의 가중치는 낮추고 잘못분류된 샘풀의 가중치는 상대적으로 높여주면서 샘플 분포를 변화시킨다.

 

반면, 그레디언트 부스트는 각 weak model을 순차적으로 적용해나가는 과정에서 잘못 분류된 샘플의 error를 최적화 하는 방식으로 진행된다.

 

이렇게 함으로써 식별하기 쉬운 데이터 특징에 대응하는 학습기부터 식별하기 어려운 데이터 특징에 대응하는 학습기까지 생성이 된다.

 

배깅과 부스팅 차이

출처:swallow.github.io

위 그림에서 나타내는 바와 같이 정리하면, 배깅은 병렬 학습

부스팅은 sequential 학습이다. 한번 학습이 끝난 후 결과에 따라 가중치를 부여한다. 그렇게 부여된 가중치가 다음 모델의 결과 예측에 영향을 준다.

 

부스팅은 배깅에 비해 error가 적다. 즉 성능이 좋다는 말이다. 하지만 속도가 느리고 오버피팅이 될 가능성이 농후하다. 그렇다면 실제 모델링을 할때 어떤 방법을 쓰는게 좋을까? 

이에 대한 답은 상황에 따라 다르다고 볼 수 있다. 개별 결정 트리의 낮은 성능이 문제라면 부스팅을 사용하고, 오버 피팅이 문제라면 배깅을 사용하면 된다. 이처럼 각자 사용할 경우를 잘 판단하는게 좋다.

 

 

[참고]

1.bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-11-%EC%95%99%EC%83%81%EB%B8%94-%ED%95%99%EC%8A%B5-Ensemble-Learning-%EB%B0%B0%EA%B9%85Bagging%EA%B3%BC-%EB%B6%80%EC%8A%A4%ED%8C%85Boosting

 

머신러닝 - 11. 앙상블 학습 (Ensemble Learning): 배깅(Bagging)과 부스팅(Boosting)

앙상블(Ensemble) 앙상블은 조화 또는 통일을 의미합니다. 어떤 데이터의 값을 예측한다고 할 때, 하나의 모델을 활용합니다. 하지만 여러 개의 모델을 조화롭게 학습시켜 그 모델들의 예측 결과들

bkshin.tistory.com

2.blog.naver.com/PostView.nhn?blogId=qbxlvnf11&logNo=221488622777&categoryNo=0&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=postView

'Machine Learning' 카테고리의 다른 글

로지스틱회귀와 활성화함수  (0) 2021.05.02
Catboost  (0) 2021.04.11

버튼,텍스트뷰,에디트텍스트 등 안드로이드에서 사용하는 위젯은 레이아웃이라는 틀 위에 존재해야 한다. 레이아웃은 위젯을 배치하여 안드로이드 화면을 목적에 맞게 배열 할 수 있게 한다.

레이아웃의 기본 개념

레이아웃은 ViewGroup 클래스로부터 상속받으며 내부에 무엇을 담는 용도로 쓰인다.

레이아웃 중에서 가장 많이 사용되는 것은 리니어 레이아웃이며, 이를 선형 레이아웃이라고도 한다.

레이아웃에서 자주 사용되는 속성

-orientation: 레이아웃 안에 배치할 위젯의 수직 또는 수평 방향을 설정

-gravity: 레이아웃 안에 배치할 위젯의 정렬 방향을 좌측,우측,중앙 등으로 설정

-padding: 레이아웃 안에 배치할 위젯의 여백을 설정

-layout_weight:레이아웃이 전체 화면에서 차지하는 공간의 가중값을 설정하는데, 여러 개의 레이아웃이 중복될 때 주로 사용

-baselineAligned:레이아웃 안에 배치할 위젯을 보기 좋게 정렬

레이아웃도 View 클래스의 하위 클래스이므로 View 클래스의 XML속서오가 메서드를 모두 사용할 수 있다.

레이아웃의 종류

자주 사용되는 레이아웃은 리니어레이아웃(LinearLayout), 렐러티브레이아웃(RelativeLayout), 프레임레이아웃(FrameLayout), 테이블레이아웃(TableLayout), 그리드레이아웃(GridLayout)등이다.

*절대 좌푯값으로 지정하는 앱솔루트레이아웃(AbsoluteLayout)도 있었으나 해상도가 다른 안드로이드폰에서 문제가 발생하여 더 이상 사용하지 않는다.

레이아웃 종류

LinearLayout(선형 레이아웃)

레이아웃의 왼쪽 위부터 아래쪽 또는 오른쪽으로 차례로 배치

RelativeLayout(상대 레이아웃)

위젯 자신이 속한 레이아웃의 상하좌우 위치를 지정하여 배치하거나 다른 위젯으로부터 상대적인 위치를 지정한다.

TableLayout

행과 열의 개수를 지정한 테이블 형태로 위젯을 배열한다.

GreedLayout

테이블레이아웃과 비슷하지만 행 또는 열을 확장하여 다양하게 배치할 때 더 편리하다.

FrameLayout

위젯을 왼쪽 위에 일률적으로 겹쳐서 배치하여 중복되어 보이는 효과를 낼 수 있다. 여러 개의 위젯을 배치한 후 상황에 따라서 필요한 위젯을 보이는 방식에 주로 활용된다.

 

=>선형레이아웃만으로도 대부분의 레이아웃 형태를 구성할 수 있어 선형레이아웃의 사용도가 가장 높다. 그러므로 선형레이아웃만 잘 이해하면 다른 레이아웃도 쉽게 이해할 수 있다.

 

 

+ Recent posts