앞으로 2주 간 인공지능과 관련된 내용들을 학습하게 될 것이다. 내가 이번 교육과정 중에서 가장 기대하는 부분이기도 하고, 지금까지는 수박 겉핥기 식으로 배웠다면 이제는 전문적으로 배우길 기대한다.
1. PyCharm 환경 구축
이번 교육은 pycharm을 통해서 진행된다. pycharm은 파이썬의 버전을 다양하게 설정하여 코딩을 할 수 있도록 지원해준다. 그렇기 때문에 pycharm의 설치부터 진행해보자.
위의 화면 처럼 설치 파일을 다운로드 받으면 아래 화면과 같은 화면이 표시된다.
다음을 누르고, 사용자 설정으로 원하는 기능을 선택한 후 설치하면 된다. 나는 모든 옵션을 선택했다.
이렇게 설치가 되다가 설치가 완료되면 시스템을 재부팅해야한다.
재부팅을 하면
이렇게 새로운 프로젝트를 생성하고, 새로운 파일을 생성할 수 있다.
프로젝트를 시작하기 앞서 numpy에 대해 알아보자.
2. Numpy 사용 이유
파이썬에는 리스트, 딕셔너리, 튜플 등이 있지만, 우리는 배열을 사용하기 위해 numpy를 사용할 예정이다.
그렇다면 왜? 배열을 사용해야 할까?
우리는 이 질문의 정답을 생각하기 이전, 자료구조와 컴퓨터 구조에 대해 알아보아야 한다.
배열을 사용하는 이유에는 두 가지가 있다. 리스트와 비교하며 알아보자.
리스트는 크기가 가변적이다. 크기가 가변적이라는 것은 메모리를 할당할 때 크기가 늘어나는 것을 염두에 두고 필요 이상의 메모리를 할당하기 때문에 낭비되는 메모리가 존재한다. 다음은 다양한 자료형을 하나의 리스트에 모두 저장이 가능하다. 이 말은 요소를 꺼내올 때마다 해당 요소가 어떤 자료형인지 확인해야하는 절차가 필요하다. 즉, 시간이 오래 걸리게 된다.
그에 비해 배열은 불변의 크기를 가지고 있다. 그렇기 때문에 낭비되는 메모리가 적고, 배열은 한 가지의 자료형만을 담기 때문에 요소를 꺼내올 때 자료형을 확인하는 절차를 거치지 않아도 된다. 즉, 시간이 짧게 걸린다.
수 많은 데이터를 다루기에는 리스트보다 배열을 사용하는 numpy가 유리하기 때문에 numpy를 보통 사용한다,
3. Numpy 기초 문법
a:np.ndarray = np.array(object=[1, 2, 3])
# a는 넘파이 자료형이고, 등호 우측은 파이썬의 리스트 자료형이기 때문에 np.array 함수를 사용하여 리스트를 배열로 변환
# 넘파이 자료형, 배열 생성
모든 자료형이 생성 함수가 있듯 numpy의 배열 또한 생성함수를 가지고 있다. 생성함수를 통해 리스트를 배열로 변환한다.
c = np.zeros(shape=(3,4)) # 크기가 3X4이고, 0으로 채워진 배열 생성
print(f'np.zeros: \n{c}')
d = np.ones(shape=(4,4)) # 크기가 4X4이고, 1로 채워진 배열 생성
print(f'np.ones: \n{d}')
빈 배열을 생성하는 방법으로, 모두 0, 혹은 모두 1로 채워진 배열의 틀을 생성한다.
np_arange = np.arange(0, 6, 1)
# 파이썬의 range함수와 동일한 기능 수행
np_linspace = np.linspace(0, 10, 100)
# 시작점(0)부터 끝점(10) 사이를 단계(100)의 수로 나눔
두 가지 코드 모두 범위에 대한 함수이지만, 차이점이 있다면 arange의 경우 시작점을 포함하는 값부터, 끝점을 포함하지 않는 값까지 정해진 단계의 수 만큼의 데이터를 선택하지만, linspace는 시작점을 포함하는 값부터, 끝 점을 포함하지 않는 값까지를 단계의 수로 나누는 범위를 이야기한다.
x = np.array([[1,2], [3,4]])
y = np.array([[5,6], [7,8]])
result_1 = np.concatenate((x, y), axis=0)
result_2 = np.concatenate((x, y), axis=1)
데이터프레임을 concat하는 것과 같이 배열을 합치는 기능을 수행하는데, 행결합을 할지, 열결합을 할지 axis 매개변수를 통해 결정한다.
array_1 = np.arange(12)
#[0,1,2,3,4,5,6,7,8,9,10,11]
array_2 = array_1.reshape(3,-1)
#[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
배열의 생성과 배열의 재구성 코드이다. reshape 메서드를 통해 원래의 배열을 원하는 사이즈로 재구성할 수 있다. 1차원 배열을 2차원으로 변경하는 등의 기능을 수행한다. 위의 코드와 같이 만약 재구성하고자 하는 크기에 '-1'이 입력될 경우 지정하는 값 외에 자동으로 데이터 크기에 맞추어 배열의 크기가 변경된다.
array_5 = np.array([1,2,3,4,5,6])
array_5_1 = array_5[np.newaxis, :] #newaxis 새로운 축 추가 (ex 1차원 -> 2차원)
array_1_5 = array_5[:, np.newaxis]
1차원 배열을 만들었다고 한들, 배열에 새로운 축을 추가해 2차원 배열로 만들 수 있다. 하지만 'array_5_1'과 'array_1_5'가 다른 것 처럼, np.newaxis 객체의 위치에 따라 가로 축을 추가할 것인지, 세로 축을 추가할 것인지 결정할 수 있다.
ages = np.array([18, 19, 25, 30, 28])
print(ages[0]) #인덱싱을 사용하면 차원이 무시된다.
# 18
print(ages[:]) #슬라이싱을 사용하면 차원은 유지됨
# [18, 19, 25, 30, 28]
print(ages[0:2])
# [18, 19]
print(ages[1:])
# [19, 25, 30, 28]
배열의 인덱싱과 슬라이싱의 차이는, 차원을 고려하느냐, 고려하지 않느냐이다. 인덱싱을 하게 되면 요소만을 가져오기 때문에 차원을 무시하지만, 슬라이싱은 범위의 데이터를 가져오기 때문에 차원이 보존된다.
scores = np.array([[99, 93, 60, ], [98, 82, 93, ], [93, 65, 81, ], [78, 82, 81, ]])
print(scores.mean(axis = 0)) # [92. 80.5 78.75]
print(scores.mean(axis = 1)) # [84. 91. 79.66666667 80.33333333]
2차원 배열의 평균을 구하는 연산이다. axis 매개변수를 이용하여 행을 기준으로 평균을 구할 지, 열을 기준으로 평균을 구할 지 지정할 수 있다.
import matplotlib.pyplot as plt
x = np.arange(0, 20) # 독립변수: 벡터 x가 가지는 범위
y1 = 2 * np.ones(20) # 상수함수
y2 = x # 선형함수
y3 = np.square(x) # 비선형 함수
plt.plot(x, y1, x, y2, x, y3)
plt.show()
파란색 선그래프가 상수함수, 주황색 선그래프는 선형함수, 초록색 선그래프는 비선형 함수를 의미한다.
상수함수는 x의 값에 관계 없이 항상 일정한 값을 출력하는 함수를 의미하고, 선형함수는 직선의 형태를 띠는 함수를 의미한다. 그 외로 곡선의 형태를 띠는 함수는 비선형 함수이다.
4. 다차원 배열의 평탄화
파이썬에서 다차원 배열을 평탄화(flattening) 하는 것은 배열을 단일 차원 배열, 즉 1차원 배열로 변환하는 작업을 의미한다. 이를 통해 여러 차원의 중첩된 리스트 구조를 단일 리스트로 펼칠 수 있다. 이 작업은 데이터 전처리나 배열의 각 요소에 동일한 작업을 수행할 때 유용하게 사용된다.
x = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
result = x.flatten()
print(f'result : {result}')
# result : [1 2 3 4 5 6 7 8 9 10 11 12]
다차원 배열의 평탄화에는 두 가지 방법이 있는데, flatten메서드와, ravel 메서드가 있다. 이 두 함수의 차이는 값 복사, 참조 복사에 대한 차이이다.
4-1. 얕은 복사 vs 깊은 복사
복사에는 두 가지 종류가 존재한다. 얕은 복사, 깊은 복사. 얕은 복사는 참조를 복사하는 방법이고, 깊은 복사는 값을 복사하는 방법이다. 그림을 참고해보자.
a와 b는 모두 10이라는 값을 할당 받았다. 하지만, 실제 메모리 상에서는 a와 b의 값을 따로 저장하는 것이 아닌, 한 가지의 값만을 저장한 후 똑같은 주소를 할당해준다. 그렇게 되면 a를 변경했을 때 b의 값도 함께 변경될 가능성이 있다.
하지만 깊은 복사는 새로운 값을 새로운 주소에 적재하기 때문에 a 혹은 b를 수정하더라도 독립적으로 작용하기 때문에 값의 침범은 일어나지 않는다.
5. 행렬 내적
행렬 내적은 두 행렬 간의 곱셈 연산으로, 두 행렬의 각 원소를 곱한 후 합산하여 새로운 행렬을 생성한다.
행렬의 내적을 쉽게 설명하면 위와 같다. 각 요소를 곱한 뒤, 곱한 값끼리 더한 뒤 새로운 행렬을 만드는 과정을 행렬의 내적이라고 한다.
행렬의 내적에 관한 코드는 다음과 같다.
arr1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2 = np.array([[2, 2], [2, 2], [2, 2]])
result = arr1 @ arr2
result2 = arr1.dot(b=arr2)
'@'연산자를 이용하는 방법과 .dot메서드를 이용하여 행렬의 내적을 구하는 방법이 있다. 두 코드 모두 결과는 동일하다.
'ABC부트캠프 데이터 탐험가 과정' 카테고리의 다른 글
[20일차] ABC 부트캠프 분류(Classification)와 K-NN알고리 (0) | 2024.07.31 |
---|---|
[19일차] ABC 부트캠프 머신러닝의 기초 및 선형회귀 (0) | 2024.07.30 |
[17일차] ABC 부트캠프 취업 역량 강화 활동 (0) | 2024.07.28 |
[16일차] ABC 부트캠프 데이터 분석 프로젝트 발표회 (0) | 2024.07.28 |
[15일차] ABC 부트캠프 이미지 크롤링 및 프로젝트 주제 선정 (0) | 2024.07.24 |