- AWS의 EC2에서 't2.micro` instance type을 사용했습니다.
- (저의 경우에는)
ssh -i <KEY_PAIR.pem> ec2-user@ec2-3-141-143-48.us-east-2.compute.amazonaws.com으로 Instance에 접속이 가능합니다. - Inbound rule를 편집해서 8000번 포트를 개방합니다.
- 정상적으로 작동함을 확인할 수 있습니다.
- Pydantic을 통해 데이터 유효성 검사를 할 수 있는데 이점이 편리합니다.
- Swagger UI를 사용하여 자동으로 API 문서가 생성됩니다.
- 비교적 최근에 나온 프레임워크이므로 Django나 Flask와 비교하면 커뮤니티가 작고 자료도 적습니다.
- 사용한 이유는 전에 Scene text image QC server API를 FastAPI를 사용해 만들었던 업무 경험이 있어 개인적으로 익숙하기 때문입니다.
DBUser("users"table),DBPost("posts"table),DBComment("comments"table)는 각각 게시판의 사용자, 게시글, 댓글을 의미합니다.DBUser와DBPost는 one-to-many 관계입니다.DBUser와DBComment는 one-to-many 관계입니다.DBPost와DBComment는 one-to-many 관계입니다.
# 'bulletin_board/app/schemas.py'
class DBUser(BASE):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
name = Column(String, nullable=False)
email_addr = Column(String, nullable=False, unique=True)
created_at = Column(DateTime, server_default=func.now(), nullable=True)
posts = relationship("DBPost", back_populates="writer")
comments = relationship("DBComment", back_populates="writer")
class DBPost(BASE):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, unique=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
title = Column(String, nullable=False)
content = Column(String, nullable=True)
created_at = Column(DateTime, server_default=func.now(), nullable=True)
updated_at = Column(
DateTime,
server_default=func.now(),
onupdate=datetime.now,
nullable=True,
)
writer = relationship("DBUser", back_populates="posts")
comments = relationship("DBComment", back_populates="post")
class DBComment(BASE):
__tablename__ = "comments"
id = Column(Integer, primary_key=True, unique=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False)
content = Column(String, nullable=True)
created_at = Column(DateTime, server_default=func.now(), nullable=True)
updated_at = Column(
DateTime,
server_default=func.now(),
onupdate=datetime.now,
nullable=True,
)
writer = relationship("DBUser", back_populates="comments")
post = relationship("DBPost", back_populates="comments")- 게시판 서버 API의 각 HTTP method별 Header와 Body는 다음과 같습니다.
create_user |
read_users |
update_user |
delete_user |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
create_post |
read_posts |
update_post |
delete_post |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
create_comment |
update_comment |
delete_comment |
|---|---|---|
![]() |
![]() |
![]() |
bash run.sh bulletin_board- 로그를 'logs.txt'에 자동으로 기록합니다.
| 2024-04-15 20:11:39 | WARNING | Post not found; `post_id=1` | main.py | create_comment() |
| 2024-04-15 20:11:53 | INFO | Post created; user_id=1 title='T1' content='C1' | main.py | create_post() |
| 2024-04-15 20:17:31 | INFO | Comment created; user_id=1 post_id=1 content='C1' | main.py | create_comment() |
| 2024-04-15 20:17:40 | INFO | Comment created; user_id=1 post_id=1 content='C2' | main.py | create_comment() |
| 2024-04-15 20:19:16 | WARNING | User not found; `name=None email_addr='sd3da2@gmail.com'` | main.py | update_user() |
| 2024-04-15 20:19:28 | WARNING | User not found; `name=None email_addr='sd3da2@gmail.com'` | main.py | update_user() |
| 2024-04-15 20:26:21 | WARNING | User not found; `name=None email_addr='sd3da2@gmail.com'` | main.py | update_user() |
| 2024-04-15 20:26:27 | INFO | User updated; `name=None email_addr='sd3da2@gmail.com'` | main.py | update_user() |
| 2024-04-15 20:32:04 | INFO | Comment updated; content='C3' | main.py | update_comment() |
| 2024-04-15 20:34:16 | WARNING | Comment not found; `content='C3'` | main.py | update_comment() |
| 2024-04-15 20:34:41 | WARNING | Comment not found; `comment_id=3` | main.py | update_comment() |
| 2024-04-15 20:35:24 | WARNING | Comment not found; `comment_id=3` | main.py | update_comment() |
| 2024-04-15 20:35:32 | WARNING | Comment not found; `comment_id=20` | main.py | delete_comment() |
| 2024-04-15 20:35:41 | INFO | Comment deleted; `comment_id=2` | main.py | delete_comment() |
- DeepLabv3에서 DeepLabv3 ('Rethinking Atrous Convolution for Semantic Image Segmentation')를 직접 구현하고 VOC2012 (10,582 images of 'trainaug')에 대해서 학습시켰습니다.
- ImageNet-1k에 대해 학습시킨 ResNet-101 backbone을 Torchvision에서 가져와 사용했습니다.
- Loss function은 픽셀별 Cross-entropy의 합입니다.
- 학습 과정에서 최적의 모델을 선별하기 위해 Validation set에 대해 Pixel IoU를 사용했으며 21개 클래스들에 대해 평균을 구했습니다.
- CPU 환경에서도 추론이 가능하긴 하지만 느리므로 TorchScript로 변환하는 등의 방법으로 추론 속도를 향상시킬 수 있습니다.
- deeplabv3-voc2012.pt를 'instance_segmentation/resources' directory에 위치시킵니다.
bash run.sh instance_segmentation
- 구글에서 VOC2012의 클래스를 검색하로 하여 적당한 이미지를 가져와 추론시켜보겠습니다.
| 'cat', 'chair' |
|---|
![]() |
| 'person' |
|---|
![]() |
| 'airplane' |
|---|
![]() |
| 'dog', 'horse', 'person' |
|---|
![]() |
















