courses
NumPy는 데이터 사이언티스트의 도구 상자에서 핵심 구성 요소입니다. 대용량 데이터도 Python에서 효율적으로 처리할 수 있도록 해줍니다.
NumPy가 제공하는 도구 세트(손쉬운 원소별 계산, 행렬 곱, 벡터화 등)는 Python에서 복잡한 계산을 수행하는 데 최고의 선택이 되게 합니다. 따라서 면접 과정에서 자주 다뤄집니다. 이 글을 읽고 잠재적인 질문을 미리 점검해 보세요!
또한 DataCamp의 다른 자료를 통해 NumPy를 실습해 보세요.
기본 NumPy 면접 질문
다음 기본 질문으로 NumPy 기초에 대한 이해도를 점검하세요. NumPy의 기능과 목적을 확실히 아는지 확인하는 데 좋은 워밍업 질문입니다.
1. NumPy란 무엇이며, 데이터 사이언스에서 왜 사용하나요?
NumPy는 성능을 위해 많은 부분이 C/C++로 구현된 Python 패키지입니다. 주된 목표는 Python에서 대규모 데이터 배열의 계산을 더 빠르고 쉽게 만드는 것입니다. 핵심 기능은 다음과 같습니다.
- 대규모 다차원 배열과 행렬을 지원하여 큰 데이터셋을 다루는 데 필수적입니다.
- 이들 배열에서 효율적으로 동작하는 포괄적인 수학 함수를 제공해 대규모 데이터셋에서 빠른 계산을 가능하게 합니다.
- NumPy의 벡터화 연산은 복잡한 수학 연산을 효율적으로 실행할 수 있게 합니다.
- pandas, scikit-learn, SciPy 등 많은 데이터 사이언스 라이브러리의 기반이 되어 Python 데이터 사이언스 생태계의 초석 역할을 합니다.
- NumPy 배열은 Python 리스트보다 메모리 효율적이어서 빅데이터 작업 시 매우 중요합니다.
2. NumPy에서 1차원 배열을 어떻게 생성하나요?
NumPy 배열 생성은 매우 간단합니다! array() 메서드를 호출해 배열 객체를 만들면 됩니다. 1차원 배열을 만드는 법을 이해하면 더 높은 차원의 NumPy 배열도 구축할 수 있습니다.
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
3. Python 리스트와 NumPy 배열의 차이점은 무엇인가요?
Python 리스트와 NumPy 배열의 주요 차이점은 다음과 같습니다.
- 동질성: NumPy 배열은 모든 원소가 같은 타입이어야 하는 동질 구조입니다. Python 리스트는 서로 다른 타입의 원소를 포함할 수 있습니다.
- 메모리 효율: NumPy 배열은 메모리 연속 블록에 데이터를 저장하므로 Python 리스트(객체 포인터 저장)보다 메모리 효율적입니다.
- 성능: NumPy 배열은 벡터화 연산을 지원해 수치 계산에서 훨씬 빠릅니다. 명시적 반복문 없이 원소별로 연산이 수행됩니다.
- 기능성: NumPy 배열에는 배열에 직접 적용할 수 있는 다양한 수학 연산과 함수가 포함되어 있습니다. 이는 Python 리스트로는 불가능합니다.
4. NumPy 배열의 형태와 크기는 어떻게 확인하나요?
데이터 처리 중 최종 출력 배열 크기를 예상하는 경우가 많아, NumPy 배열의 형태를 확인하는 방법을 아는 것이 중요합니다.
결과가 기대에 미치지 못할 때 배열 형태를 확인하면 문제 해결에 도움이 됩니다. shape 속성으로 배열의 차원을, size 속성으로 전체 원소 수를 확인할 수 있습니다.
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.shape) # Output: (2, 3)
print(arr.size) # Output: 6
5. NumPy 배열의 형태를 어떻게 변경하나요?
배열 형태 변경은 데이터 전처리와 특징 공학에서 흔한 작업입니다. 다양한 알고리즘의 입력 요구사항에 데이터를 맞추거나 분석을 위해 데이터를 재구성하는 데 중요합니다.
reshape() 메서드나 np.reshape() 함수를 사용해 배열 형태를 변경할 수 있습니다. 방법은 다음과 같습니다.
import numpy as np
# Using reshape() method
arr = np.array([1, 2, 3, 4, 5, 6])
reshaped_arr = arr.reshape(2, 3)
print(reshaped_arr)
# Output:
# [[1 2 3]
# [4 5 6]]
# Using np.reshape() function
arr = np.array([1, 2, 3, 4, 5, 6])
reshaped_arr = np.reshape(arr, (3, 2))
print(reshaped_arr)
# Output:
# [[1 2]
# [3 4]
# [5 6]]중급 NumPy 면접 질문
이 질문들은 NumPy의 실제 활용에 더 깊이 들어갑니다. 배열에 대한 기초를 다졌다면, 이제 기능을 탐구해야 합니다. 중급 단계에서는 NumPy로 계산을 수행할 수 있어야 합니다.
6. 모든 값이 0 또는 1인 배열을 어떻게 생성하나요?
0 또는 1로 채워진 배열 생성은 행렬 초기화, 마스크 배열 생성, 플레이스홀더 데이터 구조 설정 등에서 자주 필요합니다.
NumPy에서 모두 0 또는 모두 1인 배열은 np.zeros() 또는 np.ones() 함수를 사용해 만듭니다.
import numpy as np
# Create a 3x4 array of zeros
zeros_arr = np.zeros((3, 4))
print(zeros_arr)
# Output:
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
# Create a 2x2 array of ones
ones_arr = np.ones((2, 2))
print(ones_arr)
# Output:
# [[1. 1.]
# [1. 1.]]
7. NumPy에서 브로드캐스팅이란 무엇인가요?
브로드캐스팅은 서로 다른 크기의 배열 간에도 효율적으로 연산할 수 있게 해주는 NumPy의 핵심 동작입니다.
간단히 말해, 두 배열의 형태가 호환되도록 작은 배열을 자동으로 확장해 더 큰 배열과 연산할 수 있게 합니다.
다음 예시를 보세요.
import numpy as np
a = np.array([1, 2, 3])b = np.array([[1], [2], [3]])
print(a + b)
# Output:
# [[2 3 4]
# [3 4 5]
# [4 5 6]]
8. NumPy 배열의 평균, 중앙값, 표준편차는 어떻게 구하나요?
평균, 중앙값, 표준편차는 데이터를 이해하는 데 흔히 쓰이는 핵심 기술 통계입니다. NumPy는 이를 매우 쉽게 계산할 수 있도록 전용 함수를 제공합니다.
이 계산법을 아는 것은 NumPy 활용 능력을 높이는 데 중요합니다.
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
# Mean
mean_value = np.mean(arr)
print("Mean:", mean_value) # Output: 3.0
# Median
median_value = np.median(arr)
print("Median:", median_value) # Output: 3.0
# Standard deviation
std_value = np.std(arr)
print("Standard deviation:", std_value) # Output: 1.4142135623730951
9. NumPy를 활용해 수치 데이터를 빠르게 질의하고 불리언 조건에 따라 동작을 수행하려면 어떻게 하나요?
NumPy의 주된 목적을 계산 패키지로 생각하지만, 강력한 데이터 가공 기능도 갖추고 있습니다.
불리언 인덱싱으로 데이터를 쉽게 질의하고 결과에 따라 연산을 수행할 수 있습니다. 특히 where() 메서드는 수치 값에 따라 데이터를 변경하고자 할 때 유용합니다.
예를 들어 df라는 시험 점수 데이터프레임이 있고 학생을 범주화하려 한다고 가정해 보겠습니다. 간단한 np.where()는 다음과 같습니다.
df[‘student_cat’] = np.where(df[‘score’] > 80, ‘good’, ‘bad’)
where() 메서드는 최대 3개의 입력을 받는다는 점에 유의하세요.
- 첫 번째는 불리언 조건
- 두 번째는 조건이 참일 때의 결과
- 세 번째는 조건이 거짓일 때의 결과
10. 평균제곱오차(Mean Squared Error) 같은 계산에 NumPy를 어떻게 활용할 수 있나요?
NumPy는 전체 배열을 한 번에 처리할 수 있어 평균제곱오차(MSE) 같은 계산을 간단하게 구현할 수 있습니다.
원소별로 단순 연산을 수행하므로 연산을 손쉽게 벡터화할 수 있어 MSE 계산을 효율적으로 처리합니다.
다음은 NumPy로 MSE를 구현한 예시입니다.
# 1. We have two arrays, our prediction, and actual labels
# 2. We take the squared differences and sum them
# 3. We then divide by n, which is the length of the array
n= len(labels)
error = (1/n) * np.sum(np.square(predictions - labels))
고급 NumPy 면접 질문
이제 고급 단계로 들어갑니다! 이 수준에서는 NumPy를 사용해 더 복잡한 문제를 해결할 수 있어야 합니다.
11. 굴리는 통계(rolling statistics), 예를 들어 이동 평균을 NumPy로 어떻게 계산하나요?
이동 평균 같은 롤링 통계는 데이터 사이언스에서 매우 중요합니다. 특히 시계열처럼 노이즈가 많은 데이터를 평활화하는 데 자주 사용됩니다.
NumPy의 잘 알려지지 않은 기능 중 하나가 “stride”입니다. stride를 활용하면 배열의 슬라이딩 윈도우 뷰를 만들 수 있습니다. lib.stride_tricks.sliding_window_view()를 사용하면 배열의 부분 집합을 쉽게 생성할 수 있습니다.
그 후 각 부분 집합에 대해 평균 같은 집계를 수행해 이동 평균을 얻을 수 있습니다. 예시는 다음과 같습니다.
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view
x = np.arange(6)
v = sliding_window_view(x, 3)
# This creates v, an array that contains subarrays of length 3 which reflect the size of the window.
12. 조건에 따라 다차원 배열에서 원소를 선택하는 고급 인덱싱은 어떻게 수행하나요?
인덱싱은 NumPy의 기본 기술이지만, 더 고급 인덱싱 기법을 활용하면 데이터를 더 정밀하게 슬라이스할 수 있습니다.
정수 배열 인덱싱과 불리언 인덱싱을 사용하면 특정 기준을 만족하는 데이터셋을 손쉽게 만들 수 있습니다.
import numpy as np
array = np.array([[10, 15, 20, 25],
[30, 35, 40, 45],
[50, 55, 60, 65]])
print(array) # Output:
# [[10 15 20 25]
# [30 35 40 45]
# [50 55 60 65]]
# Boolean indexing: Select elements greater than 30
condition = array > 30
print(condition) # Output:
# [[False False False False]
# [False True True True]
# [ True True True True]]
# Apply the condition to get the elements that meet the criteria
filtered_elements = array[condition]
print(filtered_elements) # Output: [35 40 45 50 55 60 65]
# Integer array indexing: Select specific elements based on row and column indices
row_indices = np.array([0, 1, 2])
col_indices = np.array([1, 2, 3])
selected_elements = array[row_indices, col_indices]
print(selected_elements) # Output: [15 40 65]
# Combining boolean and integer indexing
# Select elements from the array where the element is greater than 30 and belongs to specific indices
combined_condition = (array > 30) & ((row_indices[:, None] == np.arange(3)).any(axis=0))
filtered_selected_elements = array[combined_condition]
print(filtered_selected_elements) # Output: [35 40 45 50 55 60 65]
13. 행렬 분해나 연립방정식 풀이 같은 선형대수 연산을 NumPy로 어떻게 수행하나요?
대규모 데이터를 다루는 데이터 사이언티스트에게 행렬 분해는 필수적입니다. 데이터를 주성분으로 축소하는 일은 복잡도와 노이즈를 줄이는 첫 단계입니다.
NumPy의 linalg 모듈을 사용하면 주성분을 얻기 위한 선형대수 연산을 손쉽게 수행할 수 있습니다.
# The underlying signal is a sinusoidally modulated image
img = lena() # This is from scipy.misc import lena
t = np.arange(100)
time = np.sin(0.1*t)
true= time[:,np.newaxis,np.newaxis] * img[np.newaxis,...]
# We add some noise
noisy = real + np.random.randn(*true.shape)*255
# (observations, features) matrix
M = noisy.reshape(noisy.shape[0],-1)
# Singular value decomposition factorizes your data matrix such that:
# M = U*S*V.T (where '*' is matrix multiplication)
# * U and V are the singular matrices containing orthogonal vectors of unit length
# * S is a diagonal matrix containing the singular values of M - we can use this to calculate our PCs
# Obtain the results of SVD from our noisy matrix
U, s, Vt = np.linalg.svd(M, full_matrices=False)
# Transpose V to get our PC vectors
V = Vt.T
# PCs are already sorted by descending order of the singular values (i.e. by the proportion of total variance they explain)
# If we use all of the PCs we can reconstruct the noisy signal perfectly
S = np.diag(s)
Mhat = np.dot(U, np.dot(S, V.T))
print(“Using all PCs, MSE = %.6G" %(np.mean((M - Mhat)**2)))
14. NumPy에서 대규모 배열을 다룰 때 메모리 사용을 어떻게 최적화할 수 있나요?
NumPy의 잘 쓰이지 않는 기능 중 하나가 memmap()입니다. 배열을 파일로 저장해 메모리보다 큰 배열도 읽을 수 있게 해줍니다. 핵심 이점은 지연(lazy) 데이터 읽기로, 전체 메모리 사용량을 줄이면서도 전체 데이터셋을 다룰 수 있다는 점입니다.
이 함수를 적절히 활용하면 대용량 데이터를 더 쉽고 편리하게 처리할 수 있습니다.
import numpy as np
# Create a large array and save it to a file using memmap
filename = 'large_array.dat'
large_array_shape = (10000, 10000)
dtype = np.float32 # Specify the data type of the array
# Create a memmap object with the desired shape and dtype
large_array = np.memmap(filename, dtype=dtype, mode='w+', shape=large_array_shape)
# Initialize the array with some values (e.g., fill it with random numbers)
large_array[:] = np.random.rand(*large_array_shape)
# Access a small part of the array without loading the entire array into memory
sub_array = large_array[5000:5010, 5000:5010]
print(sub_array) # Output: A 10x10 array with random float values
# Clean up and ensure that the changes are written to disk
del large_array
15. NumPy에서 결측치나 무한대 값을 포함한 배열을 어떻게 처리하고 조작하나요?
결측치와 무한대 값 처리는 데이터 사이언티스트에게 흔한 과제입니다. 먼저 NumPy의 isnan() 또는 isinf()로 이러한 값을 찾아낼 수 있습니다.
체계적인 문제가 있다면 파이프라인을 점검하고, 그렇지 않다면 값을 대체하는 방안을 고려할 수 있습니다.
결측치를 직접 NumPy만으로 채우지 않더라도, 종종 pandas의 fillna()와 NumPy 함수를 조합해 결측을 채웁니다. 예를 들어 NumPy의 mean()이나 median()으로 오류 값을 빠르게 대체할 수 있습니다.
데이터 사이언티스트를 위한 NumPy 면접 질문
지금까지는 일반적인 NumPy 질문을 다뤘습니다. 앞서 살펴본 질문도 데이터 사이언스에 적용되지만, 여기서는 데이터 사이언티스트를 위한 구체적인 NumPy 질문을 모았습니다.
16. 2차원 배열의 각 행과 열에 함수를 빠르고 쉽게 적용할 수 있는 방법이 있나요?
때로는 각 행 또는 열에 대한 정보를 얻기 위해 사용자 정의 계산이 필요합니다. 다행히 NumPy의 apply_along_axis() 메서드를 사용하면 사용자 정의 함수를 NumPy 배열 전체의 특정 축을 따라 적용할 수 있습니다.
import numpy as np
# Create a 2D array
data = np.array([
[1, 2, 3, 4, 5],
[10, 15, 20, 25, 30],
[100, 200, 300, 400, 500]
])
# Define a function to compute the range of a 1D array
def compute_range(arr):
return np.max(arr) - np.min(arr)
# Apply the compute_range function to each row (axis=1)
ranges = np.apply_along_axis(compute_range, axis=1, arr=data)
print("Range of each row:", ranges)
# Output:
# Range of each row: [ 4 20 400]
17. 머신 러닝을 위한 특징 스케일링과 정규화를 NumPy로 어떻게 수행하나요?
데이터 정규화는 머신 러닝 모델을 제대로 학습시키는 데 필수입니다. 정규화가 없으면 특히 거리 기반 모델에서 스케일 차이가 결과에 영향을 줄 수 있습니다.
NumPy의 함수를 사용해 손쉽게 스케일링을 수행할 수 있습니다. 아래는 모든 행에 대해 실행되는 최소-최대 스케일링 예시입니다. 특징 스케일링 시 올바른 축을 선택했는지 확인하세요.
import numpy as np
data = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
# Min-Max Scaling
min_vals = np.min(data, axis=0)
max_vals = np.max(data, axis=0)
scaled_data = (data - min_vals) / (max_vals - min_vals)
print("Scaled Data:\n", scaled_data)
# Output:
# Scaled Data:
# [[0. 0. 0. ]
# [0.5 0.5 0.5 ]
# [1. 1. 1. ]]
18. NumPy 배열을 쉽게 정렬하고 인덱싱하는 방법은 무엇이 있나요?
DataFrame의 sort_values() 같은 기능이 있지만, 어떤 경우에는 정렬된 값의 위치가 필요합니다.
NumPy의 argsort()는 주어진 배열을 정렬하는 데 필요한 위치를 제공합니다. 예를 들어 정렬된 배열에 맞춰 다른 데이터셋을 올바르게 인덱싱해야 할 때 유용합니다. 위치 정보를 미리 확보해 argsort()의 출력을 활용하면 데이터셋 간 일관성을 보장할 수 있습니다.
19. NumPy의 난수 생성기에서 결과를 예측 가능하게 만드는 중요한 요소는 무엇이며, 그 이유는 무엇인가요?
컴퓨팅의 난수 생성기는 실제로는 진정한 무작위가 아니라 초기 시드에 기반합니다. 데이터와 결과를 테스트하고 쉽게 평가하려면 파이프라인의 임의성을 최소화해야 합니다.
NumPy의 random.seed() 메서드를 사용해 전체 파이프라인의 시드를 설정하면 매번 유사한 결과를 얻을 수 있습니다. 특정 시드를 설정하면 개선이 모델 조정 때문인지 무작위성 때문인지 평가할 수 있습니다.
20. NumPy로 K-평균(K-Means)을 어떻게 구현할 수 있나요?
면접에서 어떤 알고리즘을 구현해 보라는 요청을 받을 수 있습니다. 이 질문의 요지는 모델과 패키지에 대한 근본적인 이해를 보여주는 데 있습니다.
아래의 모든 코드를 외울 필요는 없지만, 핵심 단계와 필요한 메서드를 설명할 수 있어야 합니다. K-평균(및 다른 기본 알고리즘)에 대해 읽고 알고리즘이 어떻게 동작하는지 이해하세요.
import numpy as np
# Generate a sample dataset
np.random.seed(42) # For reproducibility
data = np.vstack([
np.random.normal(loc=[1, 1], scale=0.5, size=(50, 2)),
np.random.normal(loc=[5, 5], scale=0.5, size=(50, 2)),
np.random.normal(loc=[9, 1], scale=0.5, size=(50, 2))
])
def k_means(X, k, max_iters=100, tol=1e-4):
# Step 1: Initialize centroids randomly
num_samples, num_features = X.shape
centroids = X[np.random.choice(num_samples, k, replace=False)]
for i in range(max_iters):
# Step 2: Assign clusters
distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)
cluster_assignments = np.argmin(distances, axis=1)
# Step 3: Update centroids
new_centroids = np.array([X[cluster_assignments == j].mean(axis=0) for j in range(k)])
# Check for convergence
if np.all(np.linalg.norm(new_centroids - centroids, axis=1) < tol):
break
centroids = new_centroids
return centroids, cluster_assignments
# Apply k-means clustering
k = 3
centroids, cluster_assignments = k_means(data, k)
마무리 생각
NumPy로 면접 지식을 쌓는 것은 데이터 사이언스 커리어에서 성공하기 위한 중요한 단계입니다.
먼저 기초를 연습하고 이해한 뒤, 구체적 구현으로 이어가세요. NumPy를 많이 사용할수록 함수들을 더 잘 이해하고 체화하게 됩니다. 다음과 같은 DataCamp의 강의와 튜토리얼을 시도해 보세요.
FAQs
데이터 사이언스 면접에서 다뤄질 수 있는 다른 주제는 무엇인가요?
핵심 Python 프로그래밍 개념 외에도 Matplotlib, scikit-learn, SciPy 같은 라이브러리에 익숙해지는 것이 중요합니다. 이러한 도구에 대한 지식은 데이터 사이언스 면접에서 우위를 점하는 데 도움이 됩니다.
NumPy에서 알아야 할 핵심 사항은 무엇인가요?
NumPy의 최신 업데이트를 꾸준히 확인하세요. 새로운 기능과 변경 사항을 파악하고 있으면 데이터 사이언스 직무 지원 시 큰 이점을 얻을 수 있습니다.
NumPy의 일반적인 활용 사례는 무엇인가요?
NumPy는 경사하강법, 합성곱 신경망 계산 등 행렬 연산이 필요한 작업에 필수적이며, 다양한 데이터 사이언스와 머신 러닝 상황에서 매우 유용합니다.
NumPy를 효과적으로 학습하려면 어떻게 해야 하나요?
DataCamp 같은 플랫폼의 자료를 활용하고, 실습 위주로 학습하면 NumPy를 빠르고 효율적으로 익힐 수 있습니다. 실전 적용이 가장 효과적인 학습 방법입니다.
NumPy 연습을 위한 좋은 프로젝트 아이디어는 무엇인가요?
NumPy로 머신 러닝 모델을 구현해 보는 것은 수학적 역량과 라이브러리에 대한 이해를 보여주기에 훌륭합니다. K-평균 같은 간단한 프로젝트부터 시작해 경사하강법처럼 더 복잡한 과제로 확장해 보세요.