레이블이 인공지능인 게시물을 표시합니다. 모든 게시물 표시
레이블이 인공지능인 게시물을 표시합니다. 모든 게시물 표시

2025년 9월 10일 수요일

LLM 동작 메커니즘과 최신 기술 분석

이 글은 LLM 동작 메커니즘과 최신 기술 분석 내용을 나눔한다.

MoE 개념

최신 대규모 언어모델의 기술적 기법들은 크게 효율성과 성능 향상을 동시에 추구하는 방향으로 발전하고 있다. 우선 혼합 전문가 구조라 불리는 MoE 기법은 수많은 전문가 모듈 중 일부만 선택적으로 활성화하여 연산 효율을 극대화하는 방식이다. 게이트 네트워크가 입력 토큰의 은닉 상태를 보고 가장 적합한 전문가를 확률적으로 선택하고 선택된 전문가만 계산에 참여하기 때문에 전체 연산량은 줄어들면서도 특정 전문가가 특정 패턴에 특화되도록 학습된다. 이 과정에서 균형을 잡기 위해 부가적인 로드 밸런싱 손실이 함께 도입된다.

또한 파라미터 효율적 미세조정 기법들이 각광받고 있다. LoRA와 같은 방법은 거대한 모델의 전체 파라미터를 업데이트하지 않고 저차원 어댑터 행렬만 학습해도 충분히 성능을 낼 수 있도록 한다. 이 방식은 저장 공간과 학습 자원을 크게 줄이면서도 다양한 도메인에 빠르게 적응할 수 있다는 장점이 있다.

양자화와 프루닝 역시 중요하다. 양자화는 모델 파라미터를 16비트나 8비트 같은 저정밀도로 표현하여 메모리 사용량과 연산 속도를 개선한다. 프루닝은 중요도가 낮은 가중치를 제거함으로써 모델 크기를 줄이고 효율을 높인다. 이 두 기법은 실제 배포 환경에서의 속도와 비용 문제를 해결하는 핵심적 방법으로 활용된다.

메모리와 추론 속도를 개선하기 위한 기법으로는 효율적 어텐션 구조가 있다. 전통적인 어텐션은 시퀀스 길이에 따라 연산량이 제곱으로 늘어나는데 이를 완화하기 위해 플래시 어텐션과 같은 최적화 기법이 개발되었다. 이 방식은 GPU의 메모리 대역폭을 최대한 활용하면서도 연산을 줄여 긴 시퀀스 처리 능력을 크게 향상시킨다.

데이터 품질과 안전성을 강화하기 위한 학습 전략도 주목된다. 인간 피드백을 통한 강화학습 기법인 RLHF는 모델이 단순히 언어를 생성하는 수준을 넘어 사용자의 의도와 선호를 반영하도록 만든다. 최근에는 직접적인 강화학습 대신 선호 데이터만으로 지도학습을 수행하는 DPO와 같은 방식이 도입되어 학습의 안정성과 단순성이 개선되고 있다.

이와 함께 다중 모달 학습이 확대되고 있다. 텍스트뿐 아니라 이미지 음성 코드 등 다양한 데이터를 하나의 모델이 동시에 이해하고 생성할 수 있도록 설계하는 것이다. 이는 언어 중심에서 벗어나 실제 세계와 상호작용하는 범용 인공지능의 기반이 된다.

요약하면 최신 언어모델은 전문가를 선택적으로 활용하는 MoE 구조 파라미터 효율적 학습을 위한 LoRA 양자화와 프루닝 같은 최적화 메모리 효율적 어텐션 구조 인간 피드백 기반 학습 전략 그리고 다중 모달 통합 학습이라는 축 위에서 진화하고 있는 것이다.


레퍼런스

2025년 1월 13일 월요일

오픈소스 기반 2D Image to 3D model 소개

이 글은 오픈소스 기반 2D Image to 3D model (이미지 > 모델 변환)을 확인해 간략히 정리한다. 모델은 Stable Point Aware 3D, Structured 3D Latents 이다.
요즘 생각. 최근 난리인 GPU 1만개면 딥시크 10개 만들 수 있다는 모 대표님 말과 이 말에 따라 패닉하는 정부 기술투자 정책에 대해
기술 분석을 위해 누가 Structured 3D Latents 기술을 개발하고 오픈소스로 공개했나 지 궁금해 살펴보다가 이 글을 쓴다.

실무하는 기술자, 개발자들은 이미 5년전부터 하던 말인데, 이미 한국 AI는 그 당시 비교하던 미국, 유럽, 일본 뿐 아니라 중국에서도 크게 뒤져 있었다는 것이 중론이었다. 사실, 우리는 지금까지 전통적으로 OS, AI 포함 소프트웨어 분야에서 세계 시장에 제대로 된 명함을 내민 적이 별로 없다(IT강국?). 

요즘, 언론에서 딥시크로 패닉하는 뉴스 보내고 있다. 원인 중 하나로 인프라를 말하는데, 맥을 잘 못 짚어 보인다. 한참 잘못된 방향으로 기사를 쏟아내고 있어, 앞으로도 한참 멀었다는 생각이 드는 건 어쩔 수 없다. 우리나라 정부 보도자료는 이런 냄비성 기사들에 휘둘릴 정도로 전문성이 없는 듯 하다. 국회에서 모여 말하는 사람들조차 약장사들 밖에 없어, 주변 전문가들은 가기도 꺼려하는 상황이다. 여기에 엮이면 수많은 보도자료, 과제기획에 1년 이상이 없어지기 때문이다. 깊게 기술 개발할 시간만 없어진다. 보통 진짜 선수들은 운동장에서 연습하는 것을 좋아하지, 시끄럽기만 한 영양가 없는 곳은 싫어한다. 악화가 양화를 구축한지 오래라 이또한 어쩔 수 없어 보인다. 갑을 관계 제조업으로 성공한 나라의 숙명인지.. 더 생각해보면 문화의 한계라 느껴지기도..

딥러닝 좀 하는 개발자라면 알겠지만, AI 첨단 기술 중 하나가 잠재 공간에서 자유롭게 멀티모달 데이터를 학습, 변환하는 것이다. 이 스테이블 디퓨전 아키텍처를 3차원으로 자유자재로 가지고 놀 수 있는 곳은 사실 세계적으로 소수고, 대부분은 그냥 사용만 하고 있다. Structured 3D Latents가 나왔을 때 당연 미국 주요 빅테크 기업이 들어가 있는 것은 충분히 예상할 수 있었고, 중국인 개발자들도 참여했을꺼라는 생각도 했었다. 그런데, 이 논문의 저자들을 보고 속으로 약간 놀랐다. 아 애 대놓고 마이크로소프트 보다 1저자로 칭화대학 연구생들이 올라가 있었던 것이다.

1저자 학생은 칭화대 출신으로 5년전부터 마이크로소프트 인턴으로 공부하며, 미국 인프라를 사용하고 있고, 이 학생의 지도 교수조차 미국에서 공부하고 인텔 등에서 일한 경력직이다. 즉, 이 기술 개발의 숨은 스토리는 미국 빅테크 기업의 중국계 기술 경력 엔지니어를 교수로 네트웍 삼아, 중국 유학생을 보낸 후 5년째 되어, 이런 기술을 습득한 것으로 정리된다. 
상황이 이쯤 되면, 앞에 언급한 정부 정책에 대해 어떤 생각이 드는가. 
GPU 만개, 십만개 센터 구축한들, 우리가 이런 나라를 넘어서긴 매우 어려울 것 같다는 느낌이 들지 않나. 제일 큰 문제는 우리는 인재가 없다는 것이다. 인재란 것은 헝그리 정신으로 무장하고, 선진국에 건너가, 그들의 노하우를 밤새도록 공부하고, 체내화한 후, 귀국해 산업발전에 기여할 사람을 말한다. 이런 프로세스가 동작했던 적이 우리도 있었다. 사실, 왜 안되는 지, 이것도 조금만 리서치하고, 생각하면, 알 수 있는 것이다. 그리고, 수백 페이지 짜집기한 기술동향보고서 컨설팅 받는 것 보다 직접 실무 하는 사람들에게 물어보는 게 천 번 낫다. 

하드웨어 물량 예산 퍼부어도 이를 사용할 경력있는 전문가, 개발자가 없으면 의미가 있을까? 약장사들(물건파는)만 돈 벌고 끝날 것이다. 약장사들이 돈 가져갈 수록 이들 숫자만 많아질 것이고.. 사실, 이 예상을 하기 위해 관련 자료 리처치한 노력은 30분도 안 걸렸다. 정부는 기술 전문가는 커녕, 전문가를 알아볼 사람들조차 없다는 것이 진짜 위기일 듯 하다. 

예를 들어, 허깅페이스나 깃허브를 TV에서 처음 듣고, 라스베거스쇼에서 지인과 구경 다닌 후 보도자료 내는 상황이면 그 기술에 대한 정책과 투자를 결정하는 자리에 있어서는 안 될 것이다. 전문가도 없고, 리더쉽도 부재라, 정책 거버넌스는 혼돈 그 자체, 기술 투자와 발전에 대한 시장 신뢰가 없어지면, 산업은 각자도생이고, 약장사들만 판치게 된다. 그런데 사람들은 K팝 듣는 외국인들보고 선진국이라 정신승리하고 있으니... 산업이 없으면 K문화도 없다. 

이 상황 AI만 이럴까? -  2025.3.3

2024년 12월 7일 토요일

벡터DB, 도구, 메모리 기반 간단한 PDF, Web 검색 에이전트 개발과 랭체인 라이브러리 설명

이 글은 벡터DB, 도구, 메모리 기반 간단한 PDF, Web 검색 에이전트 개발과 랭체인 라이브러리를 설명한 것이다. 참고로, Langchain은 급속히 버전과 함수가 개선되고 있어 API가 자주 변경되는 경향이 있다(Deprecated error). 이런 이유로, 작업 시 가상환경에서 개발하고, 관련 버전을 기록해 두는 것이 좋다. 
에이전트 예시(Build Ask Data app - Streamlit)
에이전트 예시(Local_RAG_Agents_Intel_cpu)

LangChain 설명 및 사용법은 앞의 블로그 내용(검색)을 참고한다. 다음 같은 순서로 LLM이 사용된다는 것만 이해하고 있으면 코드 사용에 큰 어려움은 없을 것이다. 

사용자 입력 > 컨텐츠 검색 입력 > 에이전트 도구에서 데이터 입력 > 과거 메모리 내용 입력 > 프롬프트 생성 > LLM 전달 > 추론 내용 출력

설치 
파이썬, 아나콘다가 준비되어 있다는 가정에서, 라이브러리 설치는 다음과 같다. 
pip install --upgrade openai langchain-openai langchain langchain-experimental

이 글은 OpenAI API Key, Tavily API Key를 신청해 가지고 있다고 가정한다. 실행 시 로그나 성능을 확인하고자 한다면, Langsmith에 가입한다. 각 API는 해당 웹사이트에서 가입하여 얻을 수 있다. 각 사이트에서 생성한 API키는 .env 파일을 생성해 다음과 같이 입력해 놓는다.
OPENAI_API_KEY=<OpenAI API Key>
LANGCHAIN_TRACING_V2=false
LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
LANGCHAIN_API_KEY=<Langsmith API Key>
LANGCHAIN_PROJECT=AGENT TUTORIAL

코딩
다음과 같이 코딩한다. 우선 필요한 라이브러리를 임포트한다.
import os, getpass
from openai import OpenAI  
from dotenv import load_dotenv
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain.agents import create_openai_functions_agent
from langchain_community.document_loaders import PyPDFLoader
from langchain.tools.retriever import create_retriever_tool
from langchain.agents import AgentExecutor
from langchain_openai import ChatOpenAI
from langchain import hub

os.environ["TAVILY_API_KEY"] = "input your key"
os.environ["LANGCHAIN_PROJECT"] = "AGENT TUTORIAL"
load_dotenv()
client = OpenAI(api_key="input your key")

# Travily의 웹 검색 객체 획득
web_search = TavilySearchResults(k=5) 

# PDF 데이터를 벡터DB에 청크로 저장하고, 문서 검색 객체를 획득
loader = PyPDFLoader("./202212_LiDAR.pdf")  # 적절한 PDF 입력
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
split_docs = loader.load_and_split(text_splitter)

embeddings = OpenAIEmbeddings(api_key=os.environ["OPENAI_API_KEY"])
vector = FAISS.from_documents(split_docs, embeddings)
vectordb_retriever = vector.as_retriever()
output = vectordb_retriever.get_relevant_documents(
    "PCL(Point Cloud Library) 라이브러리에 대해 설명해줘"
)[0]
print(output)  # PCL 검색 예시

pdf_retriever_tool = create_retriever_tool(
    vectordb_retriever,
    name="pdf_search",
    description="2023년 12월 PCL(Point Cloud Library) 정보를 PDF 문서에서 검색합니다. '2023년 12월 라이다 포인트 클라우드 처리 기술' 과 관련된 질문은 이 도구를 사용해야 합니다!",
) # 문서 검색 객체

# 에이전트 도구들 설정
tools = [web_search, pdf_retriever_tool]

# LLM 객체 설정
llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0)

# 프롬프트 설정
prompt = hub.pull("hwchase17/openai-functions-agent")
print(prompt.messages)

# LLM 함수 호출 에이전트 설정
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 전문가 에이전트 질문 수행
response = agent_executor.invoke(
    {
        "input": "2010년부터 PCL 라이브러리 기술에 대한 대한 내용을 PDF 문서에서 알려줘"
    }
)
print(f'답변: {response["output"]}')

우선 PDF에서 검색하라고 에이전트에게 명령했으므로, tools에 등록된 pdf vector database를 검색하는 tool을 실행한다. 다음은 이 결과의 예이다. 


> Finished chain.
답변: PCL(Point Cloud Library)은 BSD 라이선스로 개발되어 상업 및 연구 목적에 서 무료로 사용할 수 있습니다. 이 라이브러리는 크로스 플랫폼 개발을 지원하여 리눅스, 맥, 윈도우, 안드로이드 등 다양한 운영 체제에서 사용할 수 있습니다. PCL은 잘 모듈화되어 있어 배포가 용이하며, ROS(Robot Operating System), PDAL 등 유명한 오픈소스 프로젝트에서 직접 사용됩니다....

이제, web 검색 도구를 실행해 관련 내용을 추론하고, 기존 추론된 내용은 메모리를 이용해 같이 이용해 보도록 한다. 다음 코드를 입력해 본다. 
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
message_history = ChatMessageHistory()  # 메모리 사용

agent_with_chat_history = RunnableWithMessageHistory(
    agent_executor,
    lambda session_id: message_history,
    input_messages_key="input",
    history_messages_key="chat_history",
)

response = agent_with_chat_history.invoke(
    {
        "input": "2024년부터 PCL에 대한 새로운 내용을 인터넷 웹 문서에서 알려줘"
    },
    config={"configurable": {"session_id": "MyTestSessionID"}},
)
print(f"답변: {response['output']}")

이 코드를 실행하면, 다음과 같이 travily web search 도구를 이용해, 인터넷에서 해당 질문에 대한 검색을 수행하여, 결과를 LLM이 추론한다.


추론 결과는 다음과 같다.
> Finished chain.
답변: 2024년에 대한 Point Cloud Library (PCL)의 새로운 업데이트와 관련된 정보는 다음과 같습니다:

- **GitHub Pull Requests**: 2024년에는 PCL 개발에 몇 가지 주목할 만한 기여가 있었습니다. 예를 들어, 2024년 2월 10일에 larshg에 의해 열린 [#5958 (https://github.com/PointCloudLibrary/pcl/pulls)는 기능을 두 개의 라이브러리로 분할하 
는 작업에 대한 초안입니다. 또한, 2024년 1월 15일에 larshg에 의해 열린 [#5932 (https://github.com/PointCloudLibrary/pcl/pulls)는 관련된 또 다른 기여입니다.

- **공식 문서 및 웹사이트**: PCL은 대규모 오픈 프로젝트로, 포인트 클라우드 처리를 위한 다양한 최신 알고리즘을 포함하고 있습니다. 이러한 알고리즘에는 노이즈 데이터에서 이상치를 필터링하는 것과 같은 작업을 위한 필터링, 특징 추정, 표면 재구성, 등록, 모델 피팅 및 세분화가 포함됩니다. [공식 문서](http://pointclouds.org/documentation/index.html)와 [공식 웹사이트](https://pointclouds.org/)에서는 PCL에 대한 자세한 정보와 리소스를 제공합니다.

결론
langchain의 tool 에이전트 기능을 이용하면, 파일 벡터 검색, 웹 검색, 계산, 추론, 텍스트 및 차트 생성 등과 같은 기능을 쉽게 개발할 수 있다.

참고로, langchain과 연동되는 langsmith 사이트를 방문하면, 다음과 같이 얼마나 토큰을 사용했는 지 확인할 수 있다. 
LangSmith 로그 결과

부록: langchain 라이브러리 설명
LCEL 문법
사용자 정의 체인을 위한 LCEL은 기본으로 Runnable 에서 파생되어 처리된다. 이는 다음 표준적인 인터페이스를 지원한다.
  • stream: 응답 청크를 스트리밍
  • invoke: 입력에 대한 체인을 실행 호출
  • batch: 입력 목록에 대해 체인들을 실행 호출
  • astream: 비동기적으로 응답 청크를 스트리밍
  • ainvoke: invoke의 비동기 버전
LCEL는 유닉스 파이프라인처럼 입력 | 처리 | 실행 | 출력 형태로 유연한 LLM 오케스트레이션을 지원한다.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser

model = ChatOpenAI()
prompt = PromptTemplate.from_template("Explain about {topic} as one paragraph.")
chain = prompt | model | StrOutputParser()

다음 코드를 이용해 체인 그래프의 구조를 확인할 수 있다.
chain.get_graph().nodes
chain.get_graph().edges
chain.get_graph().print_ascii()

각 체인은 이터레이션(iteration)을 이용해 각 단계를 개별 관찰, 실행, 제어할 수 있도록 한다.

Runnable
runnable을 사용하면, 프롬프트 실행 중 동적으로 입력 단계에 참여할 수 있다. 이는 프롬프트에 데이터를 전달할 수 있다.
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough # RunnablePassthrough().invoke({"num": 10})
from langchain_core.runnables import RunnableLambda, RunnablePassthrough

prompt = PromptTemplate.from_template(
    "List top {n} famous people which have birthday {today}."
)
llm = ChatOpenAI(temperature=0, model_name="gpt-4o")

chain = (
    {"today": RunnableLambda(get_today), "n": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)
print(chain.invoke({'n': 3}))

사용자 정의 람다를 지원하는 RunnableLambda, 입력에 따른 동적 라우팅 RunnableBranch, 병렬 처리 RunnableParall, 이전 내용 기억을 하는 RunnableWithMessageHistory 등이 있다. 

@chain을 사용하면, 알아서 RunnableLambda로 주어진 함수를 래핑한다.
@chain
def custom_chain(text):
    chain1 = prompt1 | ChatOpenAI(model="gpt-4o-mini") | StrOutputParser()
    output1 = chain1.invoke({"topic": text})
    chain2 = prompt2 | ChatOpenAI(model="gpt-4o-mini") | StrOutputParser()
    return chain2.invoke({"sentence": output1})

체인 직렬화
앞서 정의한 LLM 체인을 직렬화(langchain_core.load)하면, 개별로 파일 저장해, 필요 시 동적으로 로딩하여 사용할 수 있다. 

OutputFixingParser
출력 파싱 시 발생하는 오류를 자동으로 수정한다. 

Caching
이미 얻은 답변을 캐쉬처리 하여, LLM API 호출을 줄여주고, 실행 속도를 높여준다. InMemoryCache, SQLiteCache 등이 있다.

PydanticOutputParser
LLM 출력을 기계처리 가능한 구조화된 형태로 변환하는 파서이다. 다음은 그 예이다. 
class EmailSummary(BaseModel):
    person: str = Field(description="person who send email")
    email: str = Field(description="email address of sender")
    subject: str = Field(description="email title")
    summary: str = Field(description="email's summerized text")
    date: str = Field(description="meeting date and time in email")

parser = PydanticOutputParser(pydantic_object=EmailSummary)
print(parser.get_format_instructions())

이와 유사한, StructuredOutputParser, JsonOutputParser, PandasDataFrameOutputParser 등이 있다.

LLM 모델 종류
lanchain이 지원하는 주요 LLM 모델은 openai, anthropic claude, cohere aya, facebook llama, microsoft phi, google gemini (ChatGoogleGenerativeAI), GPT4All 등이 있다. 이 중 몇몇 모델은 멀티모달을 지원한다.
gemini = ChatGoogleGenerativeAI(model="gemini-1.5-pro-latest")

system_prompt = (
    "You're writer. From given image, write short novel."
)

user_prompt = "Write short novel from the follow image."

multimodal_gemini = MultiModal(
    llm, system_prompt=system_prompt, user_prompt=user_prompt
)
IMAGE_URL = "house.jpg"
answer = multimodal_gemini.stream(IMAGE_URL)

LLM 모델 로컬 실행
LLM 모델을 로컬 PC에서도 실행할 수 있다. 이 경우, 허깅페이스, Ollama를 이용한다. 
llm = HuggingFacePipeline.from_model_id(
    model_id="beomi/llama-2-ko-7b",  
    task="text-generation",  
    pipeline_kwargs={"max_new_tokens": 512},
)

llm = ChatOllama(model="EEVE-Korean-10.8B:latest")

문서 로더
LangChain은 매우 다양한 문서 종류를 지원한다. PDF, CSV, Excel, Word, Web, JSON, Arxiv 등을 지원한다.

문서 청크 분할 및 요약
문서를 LLM에 입력 가능하도록 청크로 분할하는 CharacterTextSplitter(/n 기준 분할), 재귀적 문서 분할, 토큰 제한 분할, 의미론적 분할, 코드 분할, HTML 분할, JSON 분할(RecursiveJsonSplitter) 등이 있다. 

문서를 요약하는 방법은 전체 문서 요약하는 Stuff, 분할 요약하는 Map reduce, 분할 요약 후 정리하는 Map refine 및 chain of density, clustering map refine 방법 등이 있다. 

임베딩 모델
문서의 청크를 검색 가능한 벡터 형태의 임베딩 벡터로 변환하는 모델을 말한다. 보통, OpenAIEmbedding, CacheBackedEmbeddings, HuggingFace Embeddings, OllamaEmbeddings, GPT4All 등이 사용된다. 

벡터 데이터베이스와 검색기
보통, Chroma, Vectordatabase, FAISS, Pinecone 등이 사용된다. 여기서 원하는 임베딩 벡터를 검색해 문서를 리턴하는 방법은 vectorstore 기반 similarity search, MMR, ContextualCompressionRetriever(압축 검색), ContextualCompressionRetriever(컨테텍스트 압축), LongContextReorder(긴 문맥 기록), ParentDocumentRetriever(계층적 문서 검색), MultiQueryRetriever(다중 질의 후 검색), SelfQueryRetriever 등이 있다.

이와 더불어, 재순위(Reranker)를 이용해, 원하는 답을 검색할 때까지 우선순위를 조정할 수 있다. Cross Encoder Reranker, Cohere reranker, Jina Reranker, FlashRank reranker 등이 있다.

메모리
채팅과 같이 앞의 입출력에 대한 맥락을 기억해야 할 때 사용한다. RunnableWithMessageHistory 등이 있다.

Fallback 오류 방지
만약 체인 실행 중 여러 이유로 에러가 발생할 경우, 다시 재 시도하는 방법이 폴백이다. with_fallbacks 함수를 사용한다.

도구와 에이전트
앞서 언급한 도구나 사전 정의된 에이전트를 이용하면, 멀티 에이전트를 만들 수 있다. 도구들 중에서는 파일관리 도구, 이미지 생성 도구, 보고서 작성 도구 등이 있다.
랭체인 무료 제공 도구 예

예를 들어, agent_toolkits에는 langchain 커뮤니티 생태계에서 업로드한 다양한 에이전트가 있다. 이 중에 엑셀 분석 에이전트, SQL agent인 create_sql_agent 등은 많이 사용된다.
랭체인 커뮤니티 제공 에이전트 예

이런 에이전트는 BaseToolkit, BaseTool, RunnableSerializable를 기본 클래스로 파생되어 개발할 수 있다. 이 클래스의 아키텍처는 컴포짓(Composite) 디자인 패턴으로 다음과 같다.
도구를 정의할 때 앞의 @chain 처럼 @tool 데코레이터를 사용할 수도 있다. description은 어떤 도구를 LLM이 선택할 지를 체인에서 결정하는 힌트로 동작한다. 예는 다음과 같다.
import re
import requests
from bs4 import BeautifulSoup
from langchain.agents import tool

@tool
def get_word_length(word: str) -> int:
    """Returns the length of a word."""
    return len(word)

@tool
def add_function(a: float, b: float) -> float:
    """Adds two numbers together."""
    return a + b

@tool
def naver_news_crawl(news_url: str) -> str:
    """Crawls a naver.com news article and returns the body content."""
    response = requests.get(news_url)
    if response.status_code == 200:
        soup = BeautifulSoup(response.text, "html.parser")
        title = soup.find("h2", id="title_area").get_text()
        content = soup.find("div", id="contents").get_text()
        cleaned_title = re.sub(r"\n{2,}", "\n", title)
        cleaned_content = re.sub(r"\n{2,}", "\n", content)
    else:
        print(f"HTTP fail code: {response.status_code}")
    return f"{cleaned_title}\n{cleaned_content}"

tools = [get_word_length, add_function, naver_news_crawl]

from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
llm_with_tools = llm.bind_tools(tools)

LLM 평가
생성 결과에 대한 평가 방법은 자동 계산이 가능한 BLEU, ROUGE, METEOR, SemScore, 수동 평가, 작업 기반 평가, LLM 기반 평가 등이 있다. 평가용 라이브러리는 RAGAS, LangSmith, W&B 등이 있다.

평가를 위해, 테스트 데이터셋을 from ragas.testset.generator import TestsetGenerator 를 통해 자동 생성할 수 있다. 다만, 토큰 비용이 과대해 질 수 있는 문제가 발생할 수 있다. 이 경우, 오픈소스 LLM 모델을 사용할 수 있다.


2022년 12월 12일 월요일

ChatGPT-3 인공지능 기반 자동 프로그래밍 사용기, 장점과 단점

최근, 핫한 ChatGPT-3 를 이용한 인공지능 기반 자동 코딩 사용기, 그리고 GPT 장점과 단점을 정리해 공유한다.

일부 언론에서는 ChatGPT를 이용해, 인공지능이 자동으로 소프트웨어 개발을 할 수 있는 것처럼 이야기하는 데(기사 참고 - 오픈AI가 선보인 '챗GPT'에 IT업계 '들썩'..."대화 넘어 코딩·원고 작성까지) 사실은 현실과는 거리가 있다.

ChatGPT 테스트
실제 몇 가지 테스트를 해보면, 잘 알려진 특정 분야(코드 개발 패턴이 정형화되어 있는 알고리즘. 후술)에 한에 쓸만한 코드를 만들어 낸다. 

ChatGPT를 이용해, BIM(Building Information Modeling)에서 주로 많이 사용되는 IfcOpenShell 을 이용해 특정 속성을 검색하는 코드를 생성해 보겠다. 

ChatGPT 사용 순서는 다음과 같다. 
1. https://chat.openai.com/chat 에 로그인, 접속한다.
2. 다음 문장을 프롬프트에 입력한다.
load BIM.ifc using IfcOpenShell and return the element which project name is 'DDP' in python
3. ChatGPT가 학습된 소스코드를 바탕으로 유사한 패턴의 코드가 다음과 같이 생성한다. 
import ifcopenshell

# open the IFC file
ifc_file = ifcopenshell.open("BIM.ifc")

# access the building elements in the IFC file
building_elements = ifc_file.by_type("IfcBuildingElement")

# iterate over the building elements
for element in building_elements:
    # access the properties of each element
    properties = element.IsDefinedBy
    for property in properties:
        # check if the property name is "Project" and the property value is "DDP"
        if property.Name == "Project" and property.Value == "DDP":
            # return the element if the condition is met
            print(element)
            break

4. 이 코드를 직접 입력해 실행해본다. 결과는 다음과 같다. 실제로는 사용되는 API등 이 정확하지 않아, 제대로 실행되지 않는 것을 확인할 수 있다. 
ChatGPT 코드 실행

생성된 코드를 보면, for, if 문과 같이 제어문장 패턴들은 코드가 잘 생성되는 것을 알 수 있다. 몇몇 알려진 API(예. open() 함수)등도 잘 사용한다. 다만, property API는 학습 데이터가 별로 없었는지 제대로 코딩되지 않았다. 보다시피 방어적 프로그래밍은 되어 있지 않다. 유지보수성, 재활용성을 고려한 모듈화 등은 고려되지 않는 듯 보인다. 전체적으로 좀 냉정하게 보면, stack overflow 검색 구글링 시간을 줄여준 느낌이다.


GPT 장점과 단점
당연히 ChatGPT를 이용한다고, 소프트웨어가 저절로 개발되지 않는다. 다음과 같은 경우, ChatGPT는 개발에 어느정도 도움이 될 수 있다.

G1. 결과를 보면 알겠지만, for, if 와 같은 시퀀스 처리 패턴 구조는 잘 만들어 낸다. 그러므로, 특정 알고리즘(sort, search 등)과 관련된 구조는 재활용할 수 있다. 

G2. 코딩을 전혀 모르는 경우, 대략 전체적인 워크플로우를 특정 언어로 코딩해 낸다. 이는 개발 시 다양한 전문가가 모여 서비스 기능을 디자인할 때 유용할 수 있다. 예를 들어, 개발자와 디자이너가 커뮤니케이션할 때 사용할 수 있다. 

G3. 개발자가 라이브러리 기본 사용법을 잘 모르는 경우, 기본 뼈대 코드를 얻을 수 있다. Stack overflow 사이트 무한 검색 구글링 시간을 줄일 수 있다. 빠르게 그럴듯한 결과를 찾아서 정리해 준다.

G4. 개발자가 잘 알려진 라이브러리에 대해 GPT를 사용하는 경우, 예제 정도 수준의 코드를 얻을 수 있다(학습 데이터가 많은 경우).

다만, ChatGPT만으로는 다음과 같은 한계가 있다.

W1. 생성된 코드가 실행 오류가 없는 소프트웨어를 개발할 만큼 완벽하지 않다. 이전 실행 결과와 같이, 잘 알려져 있지 않은 라이브러리 사용 코드나 API 를 이해하고 있는 경우, 이는 사람이 API문서를 찾아서 적절히 코딩해야 한다. 당연하지만, ChatGPT 학습된 데이터가 부족한 데, 이런 작업을 알아서 해주지 않는다. 그렇다고, 이를 가능하게 하고자, 학습 데이터를 준비하는 것은 코딩보다 더 많은 일이 될 수 있다(가성비 문제).

W2. 데이터가 부족하면, ChatGPT는 잘못된 정보를 조합해(확률적으로 그럴듯한) 결과를 제공한다. 앞서 보았던 코딩 사례가 그렇다. ChatGPT는 주어진 데이터들의 순서열에 대한 관계를 학습한다. 그러므로, 주어진 데이터 패턴에 비슷한 결과를 짜집기해서 출력한다. 데이터가 부족한 도메인에 대한 질의는 상식적으로 말도 안되는 그럴듯한 결과를 생성한다. 사실 확인에 필요한 출처가 없다는 것도 문제가 있다. 기본 상식이 없으므로, 피드백 결과를 조작할 수도 있다.
예. 고려 시대에 성군인 의자왕에 대해 알려주세요
챗GPT. 고려시대의 의자왕(義慈王, 1216년 ~ 1259년)은 제25대 고려의 군주였습니다.

W3. 도메인 맥락을 이해하지 못한다. 소프트웨어 시스템 아키텍처 설계 관점에서 코드를 생성하지는 않는다. 이는 도메인 요구사항과 지식을 반영해 디자인되는 것이므로, 이를 코드화하는 것은 쉽지 않다. 단지, ChatGPT는 한 모듈의 코드 패턴을 생성해 낼 수 있다. 결국 아키텍처 설계자, 개발자, 도메인 전문가가 함께 붙어 작업해야 하는 부분이다.

W4. 다양한 이기종 시스템으로 부터 데이터 통합, 연계, 테스트하는 것은 현장 상황에 따라 다르므로, 이를 GPT가 대치할 수 없다. 

W5. 어차피, 개발자가 개발을 해야 한다. 앞의 W1, W2, W3, W4로 인해, 어차피 개발자가 코드를 작성해야 하고, 사용자와 요구사항 커뮤니케이션과 서비스 배포까지 고려하면, 이런 부분이 사실상 개발의 80~90% 이상을 차지한다. 

ChatGPT로 자동 작성된 코드도, 결국, 사람이 그 코드들을 이해해야, 테스트하고 품질을 검수할 수 있다(ChatGPT가 제공한 코드를 사용하다가 사고나면, GPT가 손해를 책임지는 것은 아니다). 

그래서, ChatGPT는 이전에 통합 개발환경에서 지원하던 개발보조도구의 편리한 인공지능 버전 검색 엔진 정도로 활용가능한 것이다. 당연히, 개발 과정을 대체할 수는 없을 것이다. 마찬가지 이유로, 컨텐츠를 직접 만드는 작가, 모델러, 크리에이터의 일을 대체하는 일은 없을 것이다.  다만, 컨텐츠 원본을 만드는 사람들을 제외하고, 기존 데이터를 변환(예. 번역, 상담원)하거나 짜집기(예. 문헌 조사, 동향 보고서)하는 곳들은 자동화되어 점차 가치를 얻기 어렵게 될 가능성이 높다. 

ChatGPT란 학습된 데이터를 잘조합하는 조수 역할에 적합하다. 편향된 학습데이터로는 그럴듯한 결과를 조합하는 오답의 확률이 꽤 높을 수 있다. 그러므로, 학습과정과 판단은 사람이 개입해야 한다. 챗GPT를 잘 이용하면, 챗봇의 경우와 같이 작업 생산성을 높일 수 있다(포토샵처럼 도구화될 것임). 

모든 문제를 풀어내는 인공지능 절대 솔류션은 없음

ChatGPT 조수를 잘 활용하고 싶다면, 다음 링크를 참고하라.

참고: Revit 다이나모 기반 파이썬 생성 결과
앞의 예시와 마찬가지로, 학습데이터가 부족하면, 제대로 된 결과가 생성되지 않는다. 
입력 프롭프트는 
“generate python script to make room which has 4 walls including window and door using Dynamo in Revit 2022”
였으며, 다이나모에서 실행한 결과는 다음과 같이 에러가 발생한다. 이 역시, 학습 데이터가 부족하면 제대로 된 결과를 얻지 못함을 알 수 있다. 
Dynamo Error

RevitPythonShell Error





2021년 2월 4일 목요일

식물 질병 식별 인공지능 앱 개발 방법 소개

 이 글은 식물 질병 식별 인공지능 앱 개발 방법 소개한다.

이 문제를 해결하기 위한 다양한 방법이 있었다. 그 중에 다음 링크는 시간 투자 대 효과면에서 괜찬은 방법이다. 
최근 구글 컨퍼런스에서 유사한 내용이 설명된 적이 있다. 그 부분은 이 글을 참고한다.

2021년 1월 20일 수요일

Arduino Nano 33 BLE보드와 TinyML 기반 딥러닝 처리 방법 및 사용기

이 글은 Arduino Nano 33 BLE 보드와 TinyML 기반 딥러닝 활용 방법에 대한 글이다. 

이 아두이노 마이크로 컨트롤러는 20달러로 저가 단일칩 독립형 컴퓨터이다. 웨어러블, 드론, 3D 프린터, 장난감, 스마트 플러그, 전기 스쿠터, 세탁기와 같은 장치에 내장된 컴퓨터이다. 이러한 장치를 인터넷으로 연결하면, 사물 인터넷이된다.

아두이노 커뮤니티는 TensorFlow Lite Micro를 새롭게 개발된 Arduino Nano 33 BLE Sense 보드에 도입했다. 이를 사용하면, 다양한 딥러닝 기계학습 어플리케이션을 손가락만한 아두이노 임베디드 보드에서 실행할 수 있다. 

아두이노에 사용하는 보드는 64MHz에서 실행되는 Arm Cortex-M4 마이크로 컨트롤러가 있으며 1MB 플래시 메모리와 256KB RAM이 있다. Arduino Nano 33 BLE Sense 보드는 손가락 크기보다 작다. 참고로, 임베디드 보드 개발시 다음과 같은 문제들로 데이터가 제대로 취득되지 않을 수 있다. 임베디드는 일반 컴퓨터보다 매우 민감하게 작동된다는 점을 고려해야 한다.

  • 소모 전류량 부족: 너무 많은 장치를 연결하지 않는다. 별도 전원을 준비한다.
  • 보드 불량(가끔식 발생함)
  • 회로 연결 오류: 테스터기로 확인해야 함
  • 불완전한 센서 문제: 센서 읽기에 지연, 인터럽트 사용, 보드 강제 리셋 등이 필요할 수 있음
  • 센서 간 충돌: 보드 내 조도 센서는 IMU등 다른 센서와 충돌이 있음. 테스트 필요함
  • 칩 자체 발열로 인한 센서값 오프셋: 캘리브레이션 처리가 필요하거나, 발열을 피할 수 있는 조건을 찾아야 함

이 부분은 아두이노 나노에 대한 많은 리포트에서 확인할 수 있다. 제대로 작동하지 않은 경우, 상세 내용은 다음 링크를 참고한다.

이 글은 아두이노 나노 33 센스 보드를 이용한 딥러닝 처리 방법을 간단히 이야기한다.

아두이노와 TinyML

기계 학습에는 신경망 모델을 마이크로 컨트롤러와 같은 메모리 제약있는 장치에서 실행할 때 사용할 수 있는 기술이 있다. 핵심 단계 중 하나는 부동 소수점을 8 비트 정수로 변환해 양자화하는 것이다. 이를 통해 딥러닝 계산을 더 빠르게 실행할 수 있다. 이런 임베디드 컴퓨터에서 기계학습(ML. Machine Learning) 처리하는 방법 중 하나가 TinyML이다. TinyML은 텐서플로우로 학습된 모델을 경량화해, 메모리 크기가 작은 아두이노 같은 소형 임베디드 컴퓨터에서 실행할 수 있도록 도와준다.

TinyML은 떠오르는 분야이다. 수십억 개의 마이크로 컨트롤러가 모든 종류의 장소에서 다양한 센서와 결합되어, 창의적이고 가치있는 TinyML 애플리케이션을 만들 수 있다. 아래 링크를 방문하면, TinyML 커뮤니티 글, 기술, 내용 및 예제를 확인할 수 있다.

Arduino Nano 33 BLE 기능

이 글을 따라하기 위해 다음과 같은 재료가 필요하다.

프로그래밍하려면 Arduino Web Editor를 사용하거나 Arduino IDE를 설치해야 한다. 

Arduino Nano 33 BLE Sense에는 다양한 온보드 센서가 있다.

  • 음성 – 디지털 마이크
  • 모션 – 9축 IMU (가속도계, 자이로 스코프, 자력계)
  • 환경 – 온도, 습도 및 압력
  • 빛 – 밝기, 색상 및 물체 근접

아울러, Bluetooth LE 연결이 있으므로 노트북, 모바일 앱 또는 기타 BLE 주변 장치로 데이터를 보낼 수 있다.

보드 설명 영상
보드 레이아웃

좀 더 상세한 내용은 다음 링크를 참고한다.

딥러닝 예제 실행하기

이 글 예제는 원래 TensorFlow 블로그에 Sandeep Mistry, Dominic Pajak에 의해 작성되었음을 밝힌다. 이 개발자들은 음성인식, 모션 동작 인식, 카메라 비전 사람 인식 예제를 워크샵했다. 

  • micro_speech : Yes, No 음성 인식
  • magic_wand: 동작 인식
  • person_detection: 사람 인식

딥러닝 음성 인식

첫번째 예제는 간단한 음성 명령 인식 신경망 모델을 아두이노에 업로드할 것이다. 이를 위해, 먼저 아두이노 IDE를 실행하고, 다음과 같이 Arduino Nano 33 BLE 보드와 라이브러리를 설치한다.

아두이노IDE의 도구>보드 매니저 메뉴를 실행해 다음과 같이 BLE 보드를 검색하고 설치한다.

Arduino Nano 33 BLE 보드 설치

보드를 설치한 후, Arduino 보드를 노트북과 연결한다. 그리고, IDE에서 보드와 COM 포트를 선택한다. 
USB 포트 연결
Arduino Nano 33 BLE 보드 및 포트 선택

이제, 스케치>라이브러리 매니저 메뉴를 선택해, Arduino Tensorflow Lite 를 검색해 라이브러리를 설치한다.

라이브러리 설치 후 파일>예제 메뉴에 Arduino Tensorflow 예제 중 micro_speech 예제를 선택하고, 업로드 한다. 아마, 소스를 컴파일하고 보드에 업로드하는 데 시간이 몇분 걸릴것이다.
업로드 중 모습
업로드 성공 모습

이제 툴>시리얼 모니터 메뉴를 실행한다. 그리고, 아두이노 보드를 입에 가까이 대고, Yes, No 단어를 말해보자. 그럼, 다음과 같이 음성을 인식해 Yes, No 텍스트를 출력해 준다. 

음성 딥러닝 모델 실행 모습

동작 제스쳐 인식

이 예제 실행을 위해, Arduino_LSM9DS1 라이브러리를 검색해 설치한다. 파일>예제>Arduino_TensorflowLite 예제에서 magic_wand 를 선택한다. 소스코드가 열리면, 다음과 같이 업로드한다.


성공적으로 업로드되었다면, 다음과 같이, 나노 보드를 흔들어보자. 그럼, 제스쳐에 따라, O, W와 같은 형태가 시리얼 모니터에 출력될 것이다.
제스쳐 인식 결과
제스쳐 실행 예시

사람 인식
이 예제는 ArduCam 카메라가 준비되어야 한다. 
ArduCam (구매)

카메라와 보드간 회로는 다음과 같이 연결한다.
회로 연결 모습(참고)

사람 인식 예제 실행을 위해, 파일>예제>Arduino_TensorflowLite>person_detection을 선택한다. 앞에서 한것처럼, 메뉴에서 업로드 버튼을 클릭한다. 그럼, 사람 인식 딥러닝 모델이 보드에서 실행되어, 다음과 같이 사람을 인식할 수 있다.
person detection 실행 결과

Nano 33과 배터리 연결하는 방법은 다음 자료를 참고하길 바란다.

IMU 센서 데이터 획득

보드에 내장된 IMU 자세 센서를 사용해 그 데이터값을 얻어본다. 
파일>예제>Arduino_LSM9DS1>SimpleGyroscope파일을 열고, 업로드한다. 
다음과 같이 실행되면 성공한 것이다.

OLED 디스플레이 연결

이 나노 보드에는 OLED 디스플레이가 없다. 그러므로, SSD1306 으로 불리는 OLED 디스플레이를 연결할 경우가 가끔 생긴다. 

나노 보드와 연결은 다음과 같이 한다.


아두이노 IDE에서 adafruit_SSD1306 라이브러리를 설치한다.
그리고, 다음과 같은 소스 코드를 업로드해 본다. 

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

#define OLED_RESET  -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();      // Draw many lines
  testscrolltext();    // Draw scrolling text
  testdrawbitmap(); 
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

OLED display가 동작하면 성공한 것이다. 

나노 BLE 모듈 센서 통합 테스트

앞서 정리한 내용을 응용해, 나노에 장착된 자이로센서, 가속도센서, 중력센서, 온습도 센서 등을 모두 테스트해 본다. 코드는 다음 깃허브에서 다운로드한다. 

업로드 컴파일 중 발생되는 라이브러리 헤더 에러는 앞서 설명한 대로 아두이노 라이브러리 검색 및 추가 기능으로 해결한다.

결과는 다음과 같다. 

이제, 이 나노 보드를 센싱할 건축 공간이나 부재에 부착하고, 데이터를 모아,유무선 통신으로 클라우드 플랫폼에 업로드하면, 데이터 분석을 할 수 있다. 

결론

이 글은 아두이노 나노 33 센스를 통해 TinyML을 간단히 사용해보고, 그 잠재력을 확인해 보았다. 실제 사용해 보면 알겠지만, 아직은 속도나 정확도가 그리 만족스럽지는 못하다. 다만, 손가락 크기의 보드에서 딥러닝 모델을 처리하고, 처리 데이터 결과를 클라우드 플랫폼에 전달할 수 있는 가능성이 많은 상상을 하게 만든다. 

TinyML은 응용목적에 따라 모델을 적절히 최적화한다면, 좀 더 나은 성능을 기대할 수 있을 것이다. 앞으로, 임베디드 보드를 이용한 딥러닝 처리는 더욱 보편화될 것이라 생각한다. 이 글을 통해, 관련 기술 개발 및 응용에 조금이나마 도움이 되었으면 한다.

레퍼런스






2019년 9월 12일 목요일

딥러닝 기반 3차원 포인트 클라우드 학습 및 객체 인식 방법

이 글은 대표적인 딥러닝 기반 3차원 포인트 클라우드 학습 및 객체 인식 모델 사용방법 대한 내용을 간단히 정리한다.

JSIS3D
JSIS3D는 3차원 포인트 클라우드 데이터에서 시멘틱 기반 객체 인식을 위한 딥러닝 학습 및 예측 모델이다.

JSIS3D 모델

다음은 이 모델의 github 링크이다.
사용 순서는 다음과 같다.

1. 파이썬 및 파이토치 설치
Python 3.5 이상. Pytorch 0.4 이상

CUDA를 사용할 경우, CUDA도 설치해야 한다. 버전체크는 여기를 참고한다.

2. 소스코드 & data set 다운로드
git clone https://github.com/pqhieu/jsis3d

download S3DIS dataset https://drive.google.com/open?id=1s1cFfb8cInM-SNHQoTGxN9BIyNpNQK6x
copy S3DIS dataset file to data/s3dis/h5 folder

3. 소스 빌드
cd external/densecrf
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=Release ..
make
cd ../../.. # You should be at the root folder here
make

4. 딥러닝 학습
python train.py --config configs/s3dis.json --logdir logs/s3dis

그럼, 훈련할 점군을 다운로드한 후 학습을 시작한다. 만약 CUDA 메모리 에러가 발생할 경우, config/s3dis.json 파일에 설정된 batch_size 수를 16 > 8 > 4 > 2 > 1 씩 줄여보길 바란다.

단, pytorch "ValueError: Expected more than 1 value per channel" 에러가 발생하면, batch_size를 좀 더 높여야 한다(넉넉한 GPU 메모리가 장착된 컴퓨터 권장함).

학습데이터는 이미 라벨링된 3차원 점군이 저장된 S3DIS 데이터셋이다. 참고로, S3DIS는 건물 6개 영역을 RGBD로 스캔하여 1,413 스캔 위치에서 25,434 RGBD이미지와 695,878,620 포인트 클라우드를 제공하고 있다. 스캔 데이터는 ceiling, floor, wall, beam, column, door, window, table, chair, sofa, bookcase, board 등으로 구분해 라벨링되었다.

5. 딥러닝 예측
python pred.py --logdir logs/s3dis --mvcrf

평가를 위해서는 다음 명령을 입력한다.
python eval.py --logdir logs/s3dis

Point cloud semantic segmentation using 3D CNN
이 모델은 CNN(convolutional neural network)를 이용한 시멘틱 기반 세그먼테이션 딥러닝 학습 모델이다. github 링크는 다음과 같다.
1. pytorch install
앞서 설명한 내용 참고.

2. 소스 빌드 및 데이터 준비
git clone https://github.com/nsavinov/semantic3dnet
cd build
./setup.sh
./build_run.sh

3. 데이터 훈련
cd ../src
./launch_training.sh

4. 데이터 예측
./launch_prediction.sh

5. 벤치마킹 결과 제출
./prepare_to_submit.sh
data/benchmark/submit.zip 파일을 http://www.semantic3d.net/submit_public.php 에 제출


레퍼런스

딥러닝 기반 3차원 객체 인식

이 글은 딥러닝 기반 3차원 객체를 인식하는 방법들을 간단히 조사해 정리한다.

PointRCNN
PointRCNN(Shaoshuai Shi, 2019)

PointSIFT
PointSIFT(Mingyang Jiang, 2018)

Votenet
Votenet(Charles R. Qi, 2019) (Version #2)

Superpoint graph
Superpoint graph(Loic Landrieu, 2018)

Complex-YOLO
Complex-YOLO(Liu, 2018)

Semantic3dnet
Semantic3dnet(hackel, 2017)

LiDAR-Bonnetal
LiDAR-Bonnetal(Andres Milioto, 2019)

JSIS3D
JSIS3D(Quang-Hieu Pham, 2019)

3D point cloud generation
3D point cloud generation(Chen-Hsuan Lin, 2018)

Multiple object tracking lidar
Multiple object tracking lidar(Praveen palanisamy, 2015)

OpenDetection
Open detection(Kripasindhu Sarkar, 2015)

레퍼런스