Skip to content

Naive Bayes 분류 #

Find similar titles

1회 업데이트 됨.

Edit
  • 작성자
    cloudgo

You are seeing an old version of the page. Go to latest version

Structured data

Category
Algorithm

Naive Bayes 분류 #

Naive Bayes 분류는 특성들 사이의 독립을 가정하는 베이즈(Bayes' theorem) 정리를 적용한 확률 분류기의 일종이다.

Naive Bayes 분류는 텍스트 분류로서, 문서를 여러 범주(예: 스팸, 스포츠, 정치) 중 하나로 판단하는 대중적인 분류 방법이다.

Naive Bayes는 분류기를 만들 수 있는 간단한 기술로써 단일 알고리즘을 통한 훈련이 아닌 일반적인 원칙에 근거한 여러 알고리즘을 이용하여 훈련된다. 모든 Naive Bayes 분류기는 공통으로 모든 특성값은 서로 독립임을 가정한다. 예를 들어, 특정 과일을 사과로 분류 가능하게 하는 특성들 (둥글다, 빨갛다, 지름 10cm)은 Naive Bayes 분류기에서 특성들 사이에서 발생할 수 있는 연관성이 없음을 가정하고 각각의 특성들이 특정 과일이 사과일 확률에 독립적으로 기여 하는 것으로 간주한다.

Naive Bayes 예제 #

데이터셋 #

목표는 해당 학습 데이터 세트로 특정 영화의 장르를 예측해보는 것이다.

dataset = {
    "movie1": {
        "genre": "Comedy",
        "words": ["fun", "couple", "love"]
    },
    "movie2": {
        "genre": "Action",
        "words": ["fast", "furious", "shoot"]
    },
    "movie3": {
        "genre": "Comedy",
        "words": ["couple", "fly", "fast", "fun"]
    },
    "movie4": {
        "genre": "Action",
        "words": ["furious", "shoot", "shoot", "fun"]
    },
    "movie5": {
        "genre": "Action",
        "words": ["fly", "fast", "shoot", "love"]
    }
}

분류 계산 정의 #

해당 영화의 어떤 태그들이 존재할 때, 이 영화가 어떤 장르에 속할 확률을 정의하면 아래와 같고,

P(Genre | Tags)

이는 조건부확률 정리 때문에 아래와 같아진다.

P(Genre | Tages) = P(Tags | Genre) * P(Genre) / P(Tags)

즉, 모든 장르에 대해 해당 태그의 확률을 구해서, 가장 큰 확률을 가지는 장르를 분류 결과로 갖는 것이다.

예를 들어, T라는 태그 집합을 가지는 영화에 대하여, 장르가 action인지 comedy인지 분류하기 위해서,

1. P(action | T) = P(T | action) * P(action) / P(T)
2. P(comedy | T) = P(T | comedy) * P(comedy) / P(T)

1과 2를 모두 구해서 확률값이 가장 큰 장르를 해당 영화의 장르라고 보는 것이다.

그런데 해당 식에서, P(T)가 분모로 중복돼서 나오므로 비교 계산에서는 크게 필요 없을 것이다.

그러므로 코드로 구현해야 할 식은 다음과 같다.

1. P(Tags | Genre) = P(tag1 | Genre) * P(tag2 | Genre) * P(tag3 | Genre)
2. P(Genre)

분류기 구현 #

먼저, 데이터 세트 안의 모든 관계에서 Genre 별 각 태그(tag)의 개수를 구한 데이터를 생성해야 한다.

def make_genre_dict(dataset):
    genre_dict = {}

    for value in dataset.values():
        genre = value['genre']
        genre_dict[genre] = {}

    for value in dataset.values():
        genre = value['genre']
        word_dict = genre_dict[genre]
        for word in value['words']:
            if word in word_dict:
                word_dict[word] += 1
            else:
                word_dict[word] = 1

    return genre_dict

이를 이용하여, 데이터 세트 안의 관계에서 장르의 개수와 장르별 태그의 개수를 구할 수 있다.

def count_genre(dataset, genre):
    genre_dict = make_genre_dict(dataset)
    count = 0
    for i in genre_dict[genre].values():
        count += i
    return count

def count_word_in_genre(dataset, word, genre):
    genre_dict = make_genre_dict(dataset)
    word_dict = genre_dict[genre]
    if word in word_dict:
        return word_dict[word]
    else:
        return 0

구해진 개수들을 이용하여, 실제 장르별 태그의 확률을 구하면 아래와 같다.

def cal_word_in_genre_p(dataset, word, genre):
    return count_word_in_genre(dataset, word, genre) / count_genre(dataset, genre)

이를 이용하여 장르별 태그 집합의 확률을 구하면 아래와 같다.

def cal_words_in_genre_p(dataset, words, genre):
    value = 1;
    for word in words:
        p = cal_word_in_genre_p(dataset, word, genre)
        value = value * p
    return value * count_genre(dataset, genre)

마지막으로, 분류기를 구현하면 된다.

def classifier(dataset, words):
    genre_dict = make_genre_dict(dataset)
    p_dict = {}
    for genre in genre_dict:
        p_dict[genre] = cal_words_in_genre_p(dataset, words, genre)
    return max(p_dict.keys(), key=p_dict.get)

결과 #

특정 영화의 태그가 fun, furious, fast라는 태그를 가질 때, 이 영화의 장르를 예측해보자.

classifier(dataset, ['fun', 'furious', 'fast'])
결과: 'Action'

이번에는 태그가 fun, love, fast일 경우를 실행해보자.

classifier(dataset, ['fast', 'love', 'fun'])
결과: 'Comedy'

참고 사이트 #

0.0.1_20240318_1_v95