은공지능 공작소 :: '분류 전체보기' 카테고리의 글 목록 (2 Page)

안녕하세요. 은공지능 공작소의 파이찬입니다.
오늘 풀어볼 문제는 "햄버거 만들기" 라는 문제입니다.

고민해 볼 포인트가 많은 문제인데요,
리스트의 일부를 효율적으로 제거하는 방법이 중요합니다.
이에 대해서 중점적으로 설명드리겠습니다.

 

 

해당 문제 바로가기 ↓↓↓ 아래 링크 클릭

https://school.programmers.co.kr/learn/courses/30/lessons/133502

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

1. 정답 공개

바로 정답 공개하도록 하겠습니다.
그 이후에 시간초과가 걸리는 코드와 정답으로 통과한 코드를 비교해 보겠습니다.
먼저, 사람들이 가장 많이 채택한 정답입니다.
def solution(ingredient):
    s = []
    cnt = 0
    for i in ingredient:
        s.append(i)
        if s[-4:] == [1, 2, 3, 1]:
            cnt += 1
            for _ in range(4):
                s.pop()
    return cnt

 

 

 

 

다음으로 시간초과로 통과할 수 없는 코드를 보여드리겠습니다.
위의 코드와 동일하나, 딱 한 줄이 다릅니다.
def solution(ingredient):
    s = []
    cnt = 0
    for i in ingredient:
        s.append(i)
        if s[-4:] == [1, 2, 3, 1]:
            cnt += 1
            s = s[:-4] # 해당 부분으로 인해 시간 초과 발생
    return cnt

 

 

 

 

 

2. Pop() 함수에 대한 이해

input_list = [1, 2, 3, 1]
input_list.pop()
print(input_list)
output
------------------------------------
[1, 2, 3]
.pop() 함수를 통해 리스트의 일부 요소를 제거할 수 있습니다.
[리스트 데이터].pop()을 사용하게 되면, 해당 리스트의 맨 마지막 요소가 제거됩니다.
이 때, 별도 변수에 리스트를 다시 할당할 필요가 없습니다.

 

 

 

input_list = [1, 2, 3, 1]
input_list.pop(0)
print(input_list)
output
------------------------------------
[2, 3, 1]
pop() 함수 안에 파라미터를 지정할 수도 있습니다.
pop 함수 안에 제거하고 싶은 리스트 요소의 인덱스 번호를 넣어주면,
리스트의 해당 요소만 제거됩니다.

위의 예시에서 pop안에 0이라고 했기 때문에,
리스트의 0번 index인 1이 제거되었습니다.

 

 

 

input_list = [1, 2, 3, 1]
a = input_list.pop(0)
print(input_list)
print('a:', a)
output
---------------------------------------
[2, 3, 1]
a: 1

 

리스트에서 튀어나온(pop) 녀석을 변수에 할당할 수도 있습니다.
위의 코드에서 튀어나온 녀석을 a라는 변수에 할당했는데요,
그래서 a의 값은 1이 됩니다.

 

 

 

def solution(ingredient):
    s = []
    cnt = 0
    for i in ingredient:
        s.append(i)
        if s[-4:] == [1, 2, 3, 1]:
            cnt += 1
            for _ in range(4):
                s.pop()
    return cnt
다시 정답 코드로 돌아가 봅시다.
리스트의 마지막 4요소가 [1, 2, 3, 1] 이면, pop함수가 4번 실행되는 구조입니다.
따로 pop 함수에 인덱스를 지정해주지 않았기 때문에,
자동으로 마지막 요소가 4번 튀어나가 제거되는 원리입니다.

 

 

 

 

 

3. 다른 풀이 (del 이용)

del 함수를 이용하여 리스트의 일부를 강제로 지울 수도 있습니다.
시간은 실행할 때마다 달라져서, 비교가 어렵네요...
pop 보다 del을 이용하는게 더 코드가 짧습니다.
def solution(ingredient):
    s = []
    cnt = 0
    for i in ingredient:
        s.append(i)
        if s[-4:] == [1, 2, 3, 1]:
            cnt += 1
            del s[-4:]
    return cnt

 

 

 

 

 

4. 마무리

오늘 문제에서 가장 중요한 포인트는
리스트에서 특정 요소를 제거하는 방법입니다.

리스트 슬라이싱을 사용하지 않고
pop이나 del을 이용하여 제거하는 방법을 익혀두시길 바랍니다.

도움이 되셨다면 하단의 하트 한 번씩 부탁드립니다!
감사합니다.

 

반응형
블로그 이미지

pychan

딥러닝에 관련된 시행착오, 사소하지만 중요한 것들, 가능한 모든 여정을 담았습니다.

,
반응형

안녕하세요. 은공지능 공작소의 파이찬입니다.
오늘은 프로그래머스의 "문자열을 정수로 바꾸기" 문제 풀어보도록 하겠습니다.
문제가 중간에 바뀌었다고 하는데.. 정말 쉽게 해결이 가능합니다!

 

 

 

사이트 문제 바로 가기 ↓↓↓

https://school.programmers.co.kr/learn/courses/30/lessons/12925

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

 

바로 해답 공개!

def solution(s):
    return int(s)
int 함수를 이용하여 바로 해결하였습니다.
만약 숫자가 아닌 문자열도 함께 있었다면, 조금 까다로운 문제였을지도 모르겠습니다...

(+)
isdigit, isnumeric 함수는 음수(-)인 정수에 대하여 필터링이 안 됩니다.
문자열 자료 중에서 음수인 정수를 필터링 할 때는 int 함수가 유용할 것입니다.

오늘은 짧게 마치겠습니다.
감사합니다.
반응형
블로그 이미지

pychan

딥러닝에 관련된 시행착오, 사소하지만 중요한 것들, 가능한 모든 여정을 담았습니다.

,
반응형

Image by Lynn Greyling (pixabay)

Downsteam task란?

최종적으로 해결하고자 하는 작업을 의미합니다.
Downstream이라는 말은 영어 그대로 직역 하면 '하류(下流)' 입니다.

물은 위에서 흘러 아래로 흘러갑니다.
즉, 상류(Upstream)에서 하류(downstream)로 흘러가는 순서가 존재합니다.

우리가 하는 작업에도 순서가 있는데, 먼저 해결해야 할 작업을 Upsteam task라 부르고
다음에 최종적으로 해결하고자 하는 작업을 Downstream task라고 합니다.
그렇다면 딥러닝에서의 Downstream task은 무엇을 의미할까요?
이는 전이학습 (Transfer Leanring)과 깊은 관련이 있습니다.

 

 

 

전이학습(Transfer learing) 이란,
모델을 처음부터 끝까지 (from scratch) 새로 훈련하는 것이 아니라,
미리 훈련된 (pre-trained) 모델로부터 학습을 시작하는 것을 의미합니다.

이를 up/down stream의 개념에 비유해보면,
upstream은 미리 훈련된 pre-trained model이 될 것이고,
downstream은 내가 최종적으로 만들고자 하는 모델이 될 것입니다.

마치 직장에서 후배가 선배의 보고서를 참조하는 것과 유사한데요,
선배가 보고서가 좋은 보고서라면 (good upstream),
후배가 보고서를 쓰기 훨씬 수월할 것입니다. (good down stream)

 

 

 

 

늑대와 호랑이를 분류하는 Downstream task를 생각해 볼까요?
개와 고양이를 분류하는 모델이 이미 학습되었다면,
이를 늑대와 호랑이를 분류하는 모델에 활용할 수 있을 것입니다.
늑대와 개 / 호랑이와 고양이는 서로 비슷한 특징을 가지고 있기 때문입니다!

딥러닝 분야에서 downstream이라는 말은 다양한 분야에서 쓰입니다.
자연어처리(NLP), 이미지 분류(image classification)등
많은 포스팅과 논문에서 Downstream이라는 단어가 등장합니다.

하지만 분야에 상관없이 모두
'내가 최종적으로 해결하고 싶은 문제',
'upstream을 거쳐 단계적으로 해결하는 것이 보다 좋은 문제'라는 점에서는 일맥상통하는 것 같습니다.

포스팅이 도움이 되셨다면, 하단의 하트와 댓글 하나씩 부탁드리겠습니다!
감사합니다.

 

반응형
블로그 이미지

pychan

딥러닝에 관련된 시행착오, 사소하지만 중요한 것들, 가능한 모든 여정을 담았습니다.

,
반응형

안녕하세요. 은공지능 공작소의 파이찬입니다.
프로그래머스의 lv.0 컨트롤제트 문제 풀어보도록 하겠습니다.

 

문제 바로가기 ↓↓↓ 하단 링크 클릭

https://school.programmers.co.kr/learn/courses/30/lessons/120853

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

1. 스택 자료 구조 이해하기

 

스택(stack) 이란, 나중에 들어간 것이 먼저 나오는 (LIFO) 자료구조를 말합니다.
문제 풀이법은 다양하지만, 저는 Stack을 이용하여 해당 문제를 풀었습니다.
자료구조를 이해하는 것은 알고리즘 문제풀이에 많은 도움이 됩니다.

 

 

 

2. 입력값을 숫자와 문자로 구분하기

input_data = "1 2 Z 3"
print('input:', input_data.split())
print()

for data in input_data.split():
    print(data)
output
-------------------------------
input: ['1', '2', 'Z', '3']

1
2
Z
3
먼저 입력 데이터를 살펴봅시다.
위와 같이 split()함수를 이용하면, 공백으로 구분된 문자열을 리스트에 이쁘게 담아줍니다.
출력을 해보면 위와 같이 프린트가 됩니다.

이제 값들을 숫자와 숫자가 아닌 것으로 구분해줘야 합니다.
그 전에 data의 값이 음수가 올 수도 있다는 사실에 주목해야 합니다.
보통 문자열 데이터에서 숫자를 구분하기 위해 isdigit(), isnumeric() 함수를 많이 사용하는데,
이 함수들은 음수값들을 필터링하지 못 합니다.

조건문에 문자열 'Z'만 따로 구분하는 방법도 있겠지만,
저는 좀 더 pythonic한 방법을 사용해보려 합니다.

 

 

 

input_data = "1 -2 Z 3"

for data in input_data.split():
    try:
        num = int(data)
        print('num:', num)
    except:
        print('str:', data)
output
--------------------------------
num: 1
num: -2
str: Z
num: 3
try ~ except 구문을 이용하였고, 음수에도 동작한다는 것을 보여드리기 위해
두 번째 입력값을 2 -> -2로 바꾸었습니다.

try ~ except는 파이썬에서 예외처리를 하기 위해 쓰이는 문법입니다.
try 쪽을 먼저 시도해보고, 에러가 안 난다면 그대로 excpet를 건너뛰고 통과합니다.
만약 try 쪽에서 에러가 난다면, except 쪽으로 빠지게 되는 구조입니다.

위의 코드에서 문자열 'Z'에 int 함수를 씌우려 하니 에러가 발생합니다.
(Exception: invalid literal for int() with base 10: 'Z')
그래서 except 구문이 실행이 되는 원리 입니다.

 

 

 

 

3. Stack 활용하여 자료 넣고 꺼내기

input_data = "1 -2 Z 3"

stack = []
for data in input_data.split():
    try:
        num = int(data)
        stack.append(num)
    except:
        if stack:
            pop_data = stack.pop()
            
    print('stack:', stack)
output
------------------------
stack: [1]
stack: [1, -2]
stack: [1]
stack: [1, 3]
Python List 자료구조를 Stack처럼 활용하였습니다.
데이터가 숫자라면 차례대로 stack에 append 함수를 이용하여 쌓아줍니다.
데이터 'Z'가 들어오면 stack에서 pop 함수를 이용하여, 마지막 것 부터 꺼냅니다.
(pop 함수는 리스트의 맨 뒤 요소를 뽑아내는 기능 수행)

(+) if stack 부분 설명:
stack에 데이터가 있으면 실행한다는 뜻 입니다.
stack이 비어있으면 if문이 실행되지 않습니다.

 

 

 

코드가 실행되는 것을 슬라이드로 표현해 보았습니다.
코드의 output을 이해하시는데 도움이 될 것입니다.

 

 

 

4. 최종 결과 값 계산하기

result라는 변수를 하나 만들고
결과들을 하나씩 더해주거나 빼주도록 하겠습니다.

숫자가 나온다면? -> result에 차례로 더해주고 stack에 쌓으면 됩니다.
'Z'가 나온다면? -> stack에서 하나를 pop한 후, result에서 빼주면 됩니다.
input_data = "1 -2 Z 3"

stack = []
result = 0
for data in input_data.split():
    try:
        num = int(data)
        result += num
        stack.append(num)
    except:
        if stack:
            pop_data = stack.pop()
            result -= pop_data

    print('result:', result)
    
print('--------------')
print('result2:', sum(stack))
output
---------------------------------------
result: 1
result: -1
result: 1
result: 4
--------------
result2: 4
result 결과값은 최종적으로 4가 됩니다.
이는 stack에 남아있는 숫자들을 모두 더한 값과 동일합니다. (result2: 4)
저도 나중에 알았네요 ㅋㅋ result 변수를 안 써도 될 듯 합니다.
최종 풀이는 해당 방법으로 교체하고 result 변수 부분들을 삭제하도록 하겠습니다.

 

 

 

 

5. 프로그래머스 제출용 정답 및 핵심정리

def solution(s):
    stack = []
    for num in s.split():
        try:
            stack.append(int(num))
        except:
            if stack:
                stack.pop()
    return sum(stack)
★핵심 정리

1. Stack 자료구조 이해 (python list 이용)
2. 음수값 처리 방법 -> python try ~ except 구문 이용
3. append와 pop의 용법 이해하기

 

 

 

 

22.11.16 판교제2테크노밸리의 소나무가 참 멋있다!

이상 포스팅을 마치겠습니다!
하트 한번씩 눌러주세요~!
감사합니다.
반응형
블로그 이미지

pychan

딥러닝에 관련된 시행착오, 사소하지만 중요한 것들, 가능한 모든 여정을 담았습니다.

,
반응형

안녕하세요. 은공지능 공작소의 파이찬입니다.
오늘부터 프로그래머스 파이썬 알고리즘 문제풀이를 하나씩 올려보려고 합니다.
거의 2년 반 만의 포스팅이네요... 이전 회사에서 너무 바쁜 나날들을 보냈습니다.

오늘 풀어볼 문제는 "로그인 성공?" 이라는 문제입니다.

 

문제 바로가기 ↓ 하단 링크 클릭

https://school.programmers.co.kr/learn/courses/30/lessons/120883

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

 

1. for문을 이용하여 input parameter 하나씩 살펴보기

 

def solution(id_pw, db):
    for id, pw in db:
        print(id, pw)
output
----------------------------
rardss 123
yyoom 1234
meosseugi 1234
아이디와 비밀번호가 각각 for문의 id, pw라는 변수에 담겼습니다.
먼저 db에 담긴 내용을 살펴보겠습니다.
현재 test case1에 대해서만 출력을 해보았는데, 결과는 위와 같습니다.

 

 

 

2. if 문으로 분기 나누기

 

그 다음으로 생각해 봐야 하는 것은 if 문으로 분기를 나누는 것입니다.
id와 pw를 비교해야 하는데, 어떤 것을 더 상위의 if문으로 둘 것인지 생각해봐야 합니다.

만약 id가 일치하는 회원이 없다면?
그냥 "fail"을 return해주고 종료하면 됩니다.
id가 틀렸는데 pw를 굳이 또 체크할 필요가 있을까요? 그럴 필요는 없습니다 ㅎㅎ

id가 일치하는 회원이 있다면, 여기서 또 분기를 2개로 나눠야 합니다.
① pw가 일치할 경우 -> "login"을 return
② pw가 일치하지 않을 경우 -> "wrong pw"를 return
def solution(id_pw, db):
    for id, pw in db:
        if id_pw[0] == id:
            if id_pw[1] == pw:
                return "login"
            else:
                return "wrong pw"
    return "fail"

 

★ 체크포인트① ★
list indexing을 이용한 id_pw 접근
id_pw는 대괄호로 묶여있는 자료구조로, 이러한 것을 python에선 list라고 부릅니다.
list의 각 요소에 접근하기 위한 방법을 indexing이라고 부르는데요,
대괄호 안의 숫자로 각 요소에 접근할 수 있습니다. (ex- id_pw[0])

+ Python index의 시작 번호는 1번 부터가 아닌 0번 부터입니다.
그러므로 id_pw[0]이라고 하는 것은, 리스트의 첫 번째 요소에 접근한다는 뜻 입니다.
id_pw = ["meosseugi", "1234"]
현재 id_pw라는 리스트는 위와 같이 구성되어 있습니다.
그러므로 id_pw[0]을 사용하면, "meosseugi"라는 id값에 접근하게 됩니다.
마찬가지 원리로 id_pw[1]는 리스트의 두 번째 요소를 가리키며,
"1234"라는 값을 반환합니다.

 

 

 

def solution(id_pw, db):
    for id, pw in db:
        if id_pw[0] == id:
            if id_pw[1] == pw:
                return "login"
            else:
                return "wrong pw"
    return "fail"
★ 체크포인트② ★
return 명령어를 활용한 함수 즉시 종료
return 명령어는 함수를 즉시 종료합니다.
해당 함수는 solution이라는 이름을 갖고 있습니다.

그러므로 위 코드를 풀이해보면,
하나라도 id와 pw가 맞는 경우가 있다면 바로 "login"을 return하고
함수가 종료된다는 뜻입니다.

만약 for문이 종료될 동안 하나도 if문에 걸리는게 없다면 어떨까요?
맨 마지막 구문인 return "fail"까지 도달하게 됩니다.
이 경우, 입력한 id와 일치하는 것이 db에 없다는 말이 되겠습니다.

 

 

 

3. 핵심 정리

해당 문제를 풀기위해 필요한 개념입니다.

ⓐ 자료구조 list에 대한 이해 (indexing 개념 포함)
for 반복문,
if 분기문
+ return을 활용한 함수 즉시 종료

해당 문제는 파이썬의 기초을 잘 알고 계신 분이라면,
무난하게 풀 수 있었던 문제라고 생각됩니다.
기초를 탄탄히 다지는 것은 언제나 중요합니다!

감사합니다.
반응형
블로그 이미지

pychan

딥러닝에 관련된 시행착오, 사소하지만 중요한 것들, 가능한 모든 여정을 담았습니다.

,

안녕하세요. 은공지능 공작소의 파이찬입니다!
정말 오랜만에 포스팅을 올리네요. 9월달은 정말 바쁘게 지낸 것 같습니다.
오늘은 tf-idf vectorizer를 생성할 때 필요한 여러가지 파라미터들에 대해 알아보겠습니다.

min_idf, analyzer, sublinear_tf, ngram_range, max_features
이렇게 5가지 파라미터들에 대해서 알아볼 것입니다.

 

 

 

 

 

 

 

 

 

 

 

 

1. 사전준비

 

 

 

from sklearn.feature_extraction.text import TfidfVectorizer

text = ['I go to my home my home is very large',
        'I went out my home I go to the market',
        'I bought a yellow lemon I go back to home']

tfidf_vectorizer = TfidfVectorizer()
우선 위와같이 데이터를 생성해 줍니다.
저번 시간에 썼던 데이터와 동일한 데이터 입니다.
오늘 사용할 파라미터는 TfidfVectorizer()의 괄호 안에 들어가는 것들입니다.

 

 

 

 

 

tfidf_vectorizer.fit(text) # 벡터라이저가 단어들을 학습합니다.
tfidf_vectorizer.vocabulary_ # 벡터라이저가 학습한 단어사전을 출력합니다.
sorted(tfidf_vectorizer.vocabulary_.items()) # 단어사전을 정렬합니다.
output:
[('back', 0),
 ('bought', 1),
 ('go', 2),
 ('home', 3),
 ('is', 4),
 ('large', 5),
 ('lemon', 6),
 ('market', 7),
 ('my', 8),
 ('out', 9),
 ('the', 10),
 ('to', 11),
 ('very', 12),
 ('went', 13),
 ('yellow', 14)]
먼저 fit 명령어를 통해서 text 변수에 저장된 데이터를 학습시켜줘야 합니다.
이렇게 학습이 끝나면, 단어사전과 idf 벡터 등을 출력해볼 수 있습니다.
단어사전은 .vocabulary_ 명령어를 통해 출력이 가능합니다.

저희는 출력을 이쁘게 하기 위해서 sorted 명령어도 같이 사용해 보았습니다.
sorted 명령어를 통해 살펴보니, 단어들은 알파벳 오름차순으로
인덱스가 부여된다는 사실도 알 수 있었습니다.

 

 

 

 

 

 

 

2. min_df 파라미터 알아보기

 

 

 

min-df는 DF(document-frequency)의 최소 빈도값을 설정해주는 파라미터입니다.
DF는 특정 단어가 나타나는 '문서의 수'를 의미합니다.
단어의 수가 아니라 문서의 수라는 것에 주의해 주세요.

DF 개념에 대해 위의 예시로 다시 설명을 드리자면
단어 'home'의 경우 전체 문서에서 빈도는 4번 이지만,
'home'이라는 단어가 포함된 문서의 수는 3개이기 때문에 DF = 3 입니다.

이러한 DF의 최소값을 설정하여 해당 값보다 작은 DF를 가진 단어들은
단어사전 (vocabulary_)에서 제외하고, 인덱스를 부여하지 않습니다.
이것이 바로 min_df 파라미터 입니다. 코드로 바로 실습해 보겠습니다.

 

 

 

 

 

min_df_vectorizer = TfidfVectorizer(min_df = 2)
min_df_vectorizer.fit(text)
sorted(min_df_vectorizer.vocabulary_.items())
output:
[('go', 0), ('home', 1), ('my', 2), ('to', 3)]
TfidfVectorizer 객체를 생성할 때, 위와 같이 min-df 파라미터를 설정하였습니다.
최소 DF가 2로 설정되었으니, 1인 것들은 모두 탈락하게 됩니다.
(PPT 설명화면에서 회색박스 글자들은 모두 DF가 1인 것들입니다.)

단어사전을 출력해보니 4개의 단어만 남았습니다.
최소 DF를 2 이상 갖는 단어들이 단어사전에 남아있게 되는 것입니다.
이 역시 알파벳 오름차순으로 인덱스를 부여받아 0 ~ 3 의 값이 할당이 되었습니다.

 

 

 

 

 

 

 

3. analyzer 파라미터 알아보기

 

 

analyzer 파라미터는 학습단위를 결정하는 파라미터입니다.
word, char 2가지 옵션 정도를 고려해볼 수 있습니다.

analyzer = 'word'라고 설정시, 학습의 단위를 단어로 설정합니다. (ex - home, go, my ...)
analyzer = 'char'라고 설정시, 학습의 단위를 글자로 설정합니다.(ex - a, b, c, d ...)

 

 

 

 

 

vectorizer = TfidfVectorizer(analyzer = 'word')
vectorizer.fit(text)
sorted(vectorizer.vocabulary_.items())
output:
[('back', 0),
 ('bought', 1),
 ('go', 2),
 ('home', 3),
 ('is', 4),
 ('large', 5),
 ('lemon', 6),
 ('market', 7),
 ('my', 8),
 ('out', 9),
 ('the', 10),
 ('to', 11),
 ('very', 12),
 ('went', 13),
 ('yellow', 14)]
analyzer = 'word'로 파라미터를 주었을 때, 단어 사전의 모습입니다.
기존의 결과와 크게 다르지 않은 모습을 보여줍니다.

 

 

 

 

 

vectorizer = TfidfVectorizer(analyzer = 'char')
vectorizer.fit(text)
sorted(vectorizer.vocabulary_.items())
output:
[(' ', 0),
 ('a', 1),
 ('b', 2),
 ('c', 3),
 ('e', 4),
 ('g', 5),
 ('h', 6),
 ('i', 7),
 ('k', 8),
 ('l', 9),
 ('m', 10),
 ('n', 11),
 ('o', 12),
 ('r', 13),
 ('s', 14),
 ('t', 15),
 ('u', 16),
 ('v', 17),
 ('w', 18),
 ('y', 19)]
analyzer = 'char'로 설정했을 때의 모습입니다.
위의 결과물처럼 각 글자마다 인덱스가 부여된 것을 확인하실 수 있습니다.

그렇다면 위와 같이 char 기반의 analyzer가 실제 모델에서
좋은 성능을 보일지 의문이 남을 수도 있을 것 같습니다.

결론부터 말씀드리면, 상당히 좋은 결과를 내놓을 수 있습니다.
제가 CNN 모델에서 char analyzer로 학습을 시킨 적이 있었는데,
생각보다 괜찮은 결과가 나왔던 것으로 기억합니다.

그러니 모델의 성능을 올리기 위해서,
word 기반 방법만 고집할 것이 아니라 char 기반의 방법도 시도해 볼 만하다고 생각합니다.

 

 

 

 

 

 

 

4. sublinear_tf 파라미터 알아보기

 

 

 

sublinear_tf 파라미터는 TF (Term-Frequency, 단어빈도) 값의
스무딩(smoothing)
여부를 결정하는 파라미터 입니다. (True/False)

TF -> 1 + ln(TF)
위와 같은 수식을 통해 스무딩 처리가 이루어집니다.
이를 이해하기 쉽도록 간단한 예제를 하나 준비해 보았습니다.

 

 

 

 

 

import numpy as np
def sublinear_func(input):
    rst = 1 + np.log(input)
    return rst
    
sublinear_func(100)
sublinear_func(10000)
output:
5.605170185988092
10.210340371976184
sublinear_tf를 구현해보는 간단한 함수를 만들어 보았습니다.
결과를 보시면 100은 5.6 정도로, 10000은 10.2 정도로 값이 확 줄어든 것을 확인하실 수 있습니다.
이처럼 sublinear_tf는 높은 TF값을 완만하게 처리하는 효과를 가지고 있습니다.

TF의 아웃라이어가 너무 심한 데이터의 경우,
이런 서브리니어 파라미터를 True로 바꿔주면 어느정도 효과를 기대할 수 있습니다.
간단히 코드 실습 후 넘어가겠습니다.

 

 

 

 

 

vectorizer = TfidfVectorizer(sublinear_tf = True) # defalut는 False입니다.
vectorizer.fit(text)
a = vectorizer.transform(text).toarray()
a
output:
array([[0.        , 0.        , 0.23427226, 0.39665741, 0.39665741,
        0.39665741, 0.        , 0.        , 0.51076864, 0.        ,
        0.        , 0.23427226, 0.39665741, 0.        , 0.        ],
       [0.        , 0.        , 0.24902824, 0.24902824, 0.        ,
        0.        , 0.        , 0.42164146, 0.3206692 , 0.42164146,
        0.42164146, 0.24902824, 0.        , 0.42164146, 0.        ],
       [0.44514923, 0.44514923, 0.26291231, 0.26291231, 0.        ,
        0.        , 0.44514923, 0.        , 0.        , 0.        ,
        0.        , 0.26291231, 0.        , 0.        , 0.44514923]])
위와 같이 sublinear_tf를 True로 설정하면, 높은 TF값들에 대해서 스무딩 처리를 해줍니다.
하지만 저희 예제 데이터는 너무 작기 때문에, 해당 파라리터의 효과가 별로 없는 것 같네요.
'TF 값에 대해 아웃라이어 처리를 해준다'라는 효과 정도만 기억하고 넘어가시면 되겠습니다.

 

 

 

 

 

 

 

5. ngram_range 파라미터 이해하기

 

 

 

n-gram이라는 것은 단어의 묶음을 말합니다.
이 단어의 묶음을 범위를 설정하는 것이 ngram_range 파라미터입니다.

예를들어, ngram_range = (1, 1)이라면 단어의 묶음을 1개부터 1개까지 설정하라는 의미입니다.
단어사전에는 1개 단어묶음에 인덱스가 할당되겠죠.
이는 기존의 벡터라이저와 별 차이가 없는 결과를 내놓습니다.

만약 ngram_range = (1, 2)라고 한다면, 단어의 묶음을 1개부터 2개까지 설정하라는 뜻입니다.
단어사전에는 1개 단어묶음도 있고, 2개 단어묶음도 존재하게 되겠죠.
가령, 'go home', 'very good'과 같은 2개 짜리 묶음도 인덱스를 받게 되는 것입니다.

 

 

 

 

 

vectorizer = TfidfVectorizer(ngram_range = (1, 1))
vectorizer.fit(text)
sorted(vectorizer.vocabulary_.items())
output:
[('back', 0),
 ('bought', 1),
 ('go', 2),
 ('home', 3),
 ('is', 4),
 ('large', 5),
 ('lemon', 6),
 ('market', 7),
 ('my', 8),
 ('out', 9),
 ('the', 10),
 ('to', 11),
 ('very', 12),
 ('went', 13),
 ('yellow', 14)]
ngram_range를 (1,1)로 설정했을 때의 모습입니다.
단어사전을 살펴보니, 기존의 벡터라이저와 별 차이가 없는 것을 볼 수 있습니다.

 

 

 

 

 

vectorizer = TfidfVectorizer(ngram_range = (1, 2))
vectorizer.fit(text)
sorted(vectorizer.vocabulary_.items())
output:
[('back', 0),
 ('back to', 1),
 ('bought', 2),
 ('bought yellow', 3),
 ('go', 4),
 ('go back', 5),
 ('go to', 6),
 ('home', 7),
 ('home go', 8),
 ...
이번에는 ngram_range를 (1, 2)로 설정해보았습니다.
이는 단어묶음을 1개부터 2개까지로 세팅하겠다는 뜻입니다.
단어사전을 출력해보니, 단어 2개 묶음도 인덱스를 받은 것을 볼 수 있습니다.

사실 이번 포스팅은 이 ngram을 설명할고 하다가,
아예 기본적인 파라미터들을 다 설명해기로 하고 만든 것입니다 ^^

그럼 이 ngram_range를 사용하는 이유는 무엇일까요?
단어가 묶여야 비로소 의미를 가지는 것들이 있기 때문입니다.
예를들어 'very'라는 단어 하나만으로는 의미를 잘 알 수 없지만
'very good', 'very bad' 등과 같이 뒤에 오는 단어가 같이 오면 정확한 의미를 알 수 있습니다.
이렇게 묶여야 의미가 살아나는 녀석들 때문에, ngram_range를 사용한다고 볼 수 있습니다.

 

 

 

 

 

6. max_features 파라미터 알아보기

 

 

 

max_feature는 tf-idf vector의 최대 feature를 설정해주는 파라미터입니다.
해당 파라미터를 이해하려면, feature의 개념에 대해 아셔야 합니다.

머신러닝에서 feature란, 테이블의 컬럼에 해당하는 개념입니다.
또한 행렬의 열에 해당하는 것이기도 합니다.

TF-IDF 벡터는 단어사전의 인덱스만큼 feature를 부여받습니다.
그럼 구체적인 예시를 코드로 한 번 살펴보겠습니다.

 

 

 

 

 

text
output:
['I go to my home my home is very large',
 'I went out my home I go to the market',
 'I bought a yellow lemon I go back to home']
저희의 데이터는 위와 같이 생겼습니다.
모두 15 종류의 단어가 사용되었는데요. 그러므로 feature값은 15가 할당이 됩니다.

 

 

 

 

 

vectorizer = TfidfVectorizer()
a = vectorizer.fit_transform(text).toarray()
a.shape
output:
(3, 15)
벡터의 shape를 출력해보면 (3, 15)가 나옵니다.
이 15라는 값이 feature에 해당하는 것입니다. 이해가 되셨죠?

이제 max_features 파라미터를 통해,
이 feature값을 10으로 제한해보겠습니다.

 

 

 

 

 

vectorizer = TfidfVectorizer(max_features = 10)
a = vectorizer.fit_transform(text).toarray()
a.shape
output:
(3, 10)
feature의 값을 10으로 제한하니, 벡터의 모양이 변했습니다.
(3, 10)으로 shape가 바뀐 것을 확인하실 수 있을 겁니다.

해당 파라미터는 어느 상황에 사용하게 될까요?
자연어처리 데이터를 다루다보면, 엄청 긴 데이터를 만날 수 있습니다.

예를 들어서 다른 데이터의 단어들은 10정도를 가지는데,
어떤 데이터만 단어 종류가 100이 넘어간다고 하면,
이 100에 맞추어 feature의 수가 엄청 늘어나게 됩니다.
그럴 경우, 모델 성능이 저하될 수도 있는 것이죠.

그렇기 때문에 사전에 EDA를 통해서 데이터의 length를 확인하시는 것이 중요합니다.
그렇게 되면 통계적으로 엄청 정확한 기준은 아닐지라도,
대략 해당 파라미터의 스타트 지점을 유추해 볼 수 있을 것입니다.

 

 

 

 

 

 

 

7. 마무리

 

 

 

네 이렇게 오늘은 tf-idf의 중요한 파라미터 5가지에 대해서 알아보았습니다.
도움이 되셨다면 포스팅 하단에 하트 버튼 한 번씩 눌러주시는 것 잊지 마세요~!

지금까지 은공지능 공작소의 파이찬이었습니다.
감사합니다.

 

반응형
블로그 이미지

pychan

딥러닝에 관련된 시행착오, 사소하지만 중요한 것들, 가능한 모든 여정을 담았습니다.

,