Python 중첩 리스트 펼치기(Nested List Flattening): 복잡한 데이터 구조를 간단하게!

중첩 리스트(Nested List)는 리스트 안에 또 다른 리스트가 포함된 데이터 구조로, 다차원 데이터를 표현하거나 복잡한 데이터 처리를 할 때 자주 등장합니다. 그러나 중첩된 리스트는 데이터를 다루는 과정을 복잡하게 만들기 때문에, 이를 한 차원으로 펼치는 작업(Flattening)이 필요합니다.

이번 글에서는 중첩 리스트를 간단히 펼치는 방법과 함께, 딥러닝이나 데이터 전처리 같은 실제 코드 상황에서 유용하게 활용할 수 있는 예제를 소개합니다.


중첩 리스트란 무엇인가?

중첩 리스트는 리스트 안에 또 다른 리스트가 포함된 구조를 말합니다. 예를 들어:

nested_list = [[1, 2, [3, 4]], [5, 6], 7]

위와 같은 중첩 리스트는 다차원 데이터를 표현하거나 계층적인 정보를 담는 데 유용하지만, 데이터를 한 차원으로 펼쳐야 할 경우 복잡한 작업이 필요합니다.


기본 중첩 리스트 펼치기 방법: 재귀 함수 사용

중첩 리스트를 펼치려면 재귀 함수를 사용하는 것이 기본적이고 가장 직관적인 방법입니다. 아래 예제는 중첩 리스트를 한 차원으로 만드는 간단한 재귀 함수를 보여줍니다.

def flatten_list(nested):
    for item in nested:
        if isinstance(item, list):
            yield from flatten_list(item)  # 재귀적으로 내부 리스트를 처리
        else:
            yield item

# 실행 예시
nested_list = [[1, 2, [3, 4]], [5, 6], 7]
flattened = list(flatten_list(nested_list))
print(flattened)

출력 결과

[1, 2, 3, 4, 5, 6, 7]

설명

  • flatten_listyield from을 사용해 중첩된 리스트를 재귀적으로 순회합니다.
  • 리스트가 아니면 값을 반환(yield)하고, 리스트라면 다시 함수 호출을 통해 내부 리스트를 처리합니다.
  • 이 방식은 중첩된 깊이에 상관없이 모든 데이터를 한 차원으로 펼칠 수 있습니다.

딥러닝 데이터 전처리에서 중첩 리스트 펼치기

딥러닝 모델을 다룰 때, 중첩된 리스트 형태의 데이터를 Flatten해야 하는 경우가 자주 있습니다. 예를 들어, 이미지 데이터나 텍스트 데이터가 계층적으로 저장되어 있을 때 이를 한 차원으로 펼쳐 모델에 입력해야 합니다.

예제: 중첩 리스트로 저장된 배치 데이터 펼치기

def flatten_batch_data(batch_data):
    for batch in batch_data:
        if isinstance(batch, list):
            yield from flatten_batch_data(batch)  # 재귀적으로 배치 데이터를 펼침
        else:
            yield batch

# 딥러닝 배치 데이터 예시
nested_batches = [
    [[1, 2], [3, 4]],  # 배치 1
    [5, [6, 7]],       # 배치 2
    8                  # 배치 3
]

flattened_data = list(flatten_batch_data(nested_batches))
print(flattened_data)

출력 결과

[1, 2, 3, 4, 5, 6, 7, 8]

설명

  • flatten_batch_data는 딥러닝 배치 데이터를 한 차원으로 펼칩니다.
  • 모델에 데이터를 입력할 때 중첩된 구조를 제거해야 한다면 이런 방식이 유용합니다.

리스트 컴프리헨션으로 중첩 리스트 펼치기

리스트 컴프리헨션은 짧고 간결한 코드 작성을 가능하게 하지만, 중첩 구조가 깊지 않을 때 적합합니다. 아래는 간단한 2차원 리스트를 펼치는 예제입니다.

nested_list = [[1, 2], [3, 4], [5, 6]]

# 리스트 컴프리헨션을 사용한 플래튼
flattened = [item for sublist in nested_list for item in sublist]
print(flattened)

출력 결과

[1, 2, 3, 4, 5, 6]

설명

  • 리스트 컴프리헨션을 사용하면 중첩 리스트의 각 요소를 한 줄로 펼칠 수 있습니다.
  • 하지만 깊이가 2 이상인 중첩 리스트에는 적합하지 않습니다. 이 경우 재귀 함수가 필요합니다.

중첩 리스트를 펼칠 때 itertools 활용하기

Python의 itertools 모듈은 복잡한 데이터 처리에 유용하며, 중첩 리스트를 처리할 때도 활용할 수 있습니다.

from itertools import chain

nested_list = [[1, 2], [3, 4], [5, 6]]

# itertools.chain으로 리스트 펼치기
flattened = list(chain.from_iterable(nested_list))
print(flattened)

출력 결과

[1, 2, 3, 4, 5, 6]

설명

  • itertools.chain.from_iterable은 리스트의 각 요소를 펼쳐줍니다.
  • 리스트의 깊이가 2차원인 경우 유용하며, 이 이상의 깊이는 재귀가 필요합니다.

실전 응용: 중첩된 JSON 데이터를 펼쳐보기

복잡한 JSON 데이터를 다룰 때 중첩된 리스트를 펼쳐야 할 경우도 있습니다. 아래는 JSON 데이터에서 리스트를 Flatten하는 예제입니다.

import json

# JSON 데이터 예시
json_data = '''
[
    {"name": "Alice", "scores": [10, 20, [30, 40]]},
    {"name": "Bob", "scores": [50, [60, 70]]}
]
'''

# JSON 파싱 및 플래튼
data = json.loads(json_data)

def flatten_json_scores(data):
    for entry in data:
        yield entry["name"], list(flatten_list(entry["scores"]))

# 실행
flattened_scores = list(flatten_json_scores(data))
print(flattened_scores)

출력 결과

[('Alice', [10, 20, 30, 40]), ('Bob', [50, 60, 70])]

설명

  • JSON 데이터를 파싱한 뒤 flatten_list를 사용해 각 scores를 펼칩니다.
  • 복잡한 JSON 데이터 구조를 Flatten하여 데이터를 쉽게 다룰 수 있도록 합니다.

결론: 중첩 리스트 펼치기의 다양한 활용

Python에서 중첩 리스트를 펼치는 작업은 데이터 전처리, 딥러닝, JSON 데이터 처리 등 다양한 상황에서 필수적입니다. 이번 가이드에서 소개한 방법들을 상황에 맞게 선택해 사용하세요:

  1. 재귀 함수: 깊이가 무제한인 중첩 리스트를 펼칠 때.
  2. 리스트 컴프리헨션: 깊이가 2인 리스트를 간단히 펼칠 때.
  3. itertools.chain: 2차원 리스트를 빠르게 펼칠 때.
  4. 딥러닝 데이터 처리: 배치 데이터를 펼쳐 모델에 입력할 때.

Python itertools 완벽 가이드: productpermutations 활용법

Python의 itertools 모듈은 반복 작업을 최적화하고 효율적으로 처리하기 위해 제공되는 강력한 라이브러리입니다. 그중에서도 productpermutations는 조합(combinations)과 순열(permutations)을 생성하여 복잡한 데이터 탐색이나 하이퍼파라미터 튜닝 작업에서 유용하게 활용됩니다. 이 글에서는 productpermutations의 개념과 실전 코드에서의 활용 방법을 알아보겠습니다.


1. itertools.product: 데카르트 곱 구현

itertools.product데카르트 곱을 계산해줍니다. 두 개 이상의 리스트를 조합해 가능한 모든 경우의 수를 반환하며, 중첩된 반복문을 간단히 대체할 수 있습니다.

기본 사용법

from itertools import product  

# 두 리스트의 데카르트 곱 계산  
colors = ["red", "green", "blue"]
sizes = ["S", "M", "L"]

combinations = product(colors, sizes)
print(list(combinations))

결과

[('red', 'S'), ('red', 'M'), ('red', 'L'), 
 ('green', 'S'), ('green', 'M'), ('green', 'L'), 
 ('blue', 'S'), ('blue', 'M'), ('blue', 'L')]

설명

  • product는 두 리스트의 모든 가능한 조합을 계산해줍니다.
  • 중첩된 반복문을 간결한 한 줄로 대체할 수 있어 코드 가독성이 높아집니다.

2. itertools.permutations: 순열 생성

itertools.permutations리스트 내 요소의 모든 순열을 생성합니다. 리스트 요소를 정렬하거나 특정 길이의 순열을 생성하는 데 유용합니다.

기본 사용법

from itertools import permutations  

# 순열 생성  
items = [1, 2, 3]
perm = permutations(items)
print(list(perm))

결과

[(1, 2, 3), (1, 3, 2), 
 (2, 1, 3), (2, 3, 1), 
 (3, 1, 2), (3, 2, 1)]

설명

  • permutations는 주어진 리스트의 모든 순열을 반환합니다.
  • 기본적으로 리스트 길이만큼의 순열을 생성하지만, r 매개변수를 사용해 지정된 길이의 순열을 생성할 수도 있습니다.

3. 실전 예제: 하이퍼파라미터 탐색

itertools.product는 머신러닝이나 딥러닝 모델의 하이퍼파라미터 탐색 작업에서 매우 유용합니다. 다양한 조합을 자동으로 생성하여 반복 작업을 줄이고 탐색 범위를 효율적으로 다룰 수 있습니다.

예제: 모델 하이퍼파라미터 튜닝

from itertools import product

# 하이퍼파라미터 후보군 정의  
learning_rates = [0.01, 0.1]
batch_sizes = [16, 32]
optimizers = ["sgd", "adam"]

# 모든 조합 생성  
parameter_grid = product(learning_rates, batch_sizes, optimizers)

# 모델 실행
for lr, batch_size, optimizer in parameter_grid:
    print(f"Training with lr={lr}, batch_size={batch_size}, optimizer={optimizer}")
    # 모델 훈련 코드 예시
    # train_model(lr=lr, batch_size=batch_size, optimizer=optimizer)

출력

Training with lr=0.01, batch_size=16, optimizer=sgd  
Training with lr=0.01, batch_size=16, optimizer=adam  
Training with lr=0.01, batch_size=32, optimizer=sgd  
Training with lr=0.01, batch_size=32, optimizer=adam  
Training with lr=0.1, batch_size=16, optimizer=sgd  
Training with lr=0.1, batch_size=16, optimizer=adam  
Training with lr=0.1, batch_size=32, optimizer=sgd  
Training with lr=0.1, batch_size=32, optimizer=adam  

설명

  • product는 하이퍼파라미터의 모든 조합을 생성해, 효율적으로 탐색 범위를 관리합니다.
  • 탐색 범위가 클수록 반복문 대신 itertools.product로 조합을 생성하는 것이 메모리와 성능 면에서 더 유리합니다.

4. 실전 예제: 작업 순서 정렬

itertools.permutations는 작업 순서를 최적화하거나, 특정 조건에 맞는 순서를 생성할 때 유용합니다. 예를 들어, 비용이 가장 적은 작업 순서를 찾는 문제에 활용할 수 있습니다.

예제: 작업 순서 조합

from itertools import permutations  

# 작업 리스트
tasks = ["task1", "task2", "task3"]

# 모든 순서 생성
task_orders = permutations(tasks)

for order in task_orders:
    print(" -> ".join(order))

출력

task1 -> task2 -> task3  
task1 -> task3 -> task2  
task2 -> task1 -> task3  
task2 -> task3 -> task1  
task3 -> task1 -> task2  
task3 -> task2 -> task1  

설명

  • permutations는 작업 순서를 자동으로 생성하여 모든 경우의 수를 테스트할 수 있습니다.
  • 이 방식은 순서가 중요한 최적화 문제에서 특히 유용합니다.

5. productpermutations를 결합하기

때로는 조합과 순열을 동시에 다루어야 하는 경우도 있습니다. 이 경우 productpermutations를 결합하면 복잡한 데이터 구조를 효율적으로 처리할 수 있습니다.

예제: 하이퍼파라미터와 데이터셋 순서 결합

from itertools import product, permutations

# 하이퍼파라미터 후보군
learning_rates = [0.01, 0.1]
optimizers = ["sgd", "adam"]

# 데이터셋 순서
datasets = ["dataset1", "dataset2", "dataset3"]

# 모든 조합 생성
parameter_grid = product(learning_rates, optimizers)
dataset_orders = permutations(datasets)

for params in parameter_grid:
    for order in dataset_orders:
        print(f"Parameters: {params}, Dataset order: {order}")

출력

(생략)

  • 모든 하이퍼파라미터 조합과 데이터셋 순서의 조합이 생성됩니다.
  • 이 방식은 모델 훈련과 데이터셋 순서를 동시에 고려할 때 유용합니다.

요약: productpermutations의 장점

  • itertools.product: 중첩된 반복문 없이 모든 조합을 효율적으로 생성합니다.
  • itertools.permutations: 리스트의 모든 순열을 자동으로 생성하여, 순서가 중요한 문제를 해결합니다.
  • 실제 활용 사례:
    1. 딥러닝 하이퍼파라미터 탐색
    2. 작업 순서 최적화
    3. 데이터셋과 설정 조합 생성

Python의 itertools를 잘 활용하면 복잡한 문제도 효율적으로 해결할 수 있습니다. 반복적인 작업을 간결하고 효과적으로 처리하고 싶다면, 지금 바로 productpermutations를 활용해보세요!

+ Recent posts