2024년 3월 30일 토요일

몬테카를로 시뮬레이션 기반 주가 예측

이 글은 몬테카를로 시뮬레이션 기반 주가 예측하는 방법을 보여준다. 

주가를 다운로드하여, 평균, 편차를 계산한 후, 95% 수준에서 시뮬레이션을 수행해, 수익률을 예측해 본다. 다음은 이를 구현한 코드이다. 

import numpy as np
import matplotlib.pyplot as plt
from eodhd import APIClient
import config as cfg

api = APIClient(cfg.API_KEY)

def get_ohlc_data():
    df = api.get_historical_data("GSPC.INDX", "d", results=365)
    return df

if __name__ == "__main__":
    df = get_ohlc_data()

    # 날짜별 계산
    daily_returns = df["adjusted_close"].pct_change().dropna()

    # 시뮬레이션 파라메터
    initial_investment = 10000  # 초기 투자량
    num_simulations = 1000    # 시뮬레이션 횟수
    forecast_days = 365    # Investment horizon in days
    desired_return = 0.10  # Desired return (10%)

    # Calculate the average daily return
    average_daily_return = daily_returns.mean()

    # Calculate volatility as the standard deviation of daily returns
    volatility = daily_returns.std()

    print(f"Average Daily Return: {average_daily_return}")
    print(f"Volatility: {volatility}")

    # Simulating future returns
    simulated_end_returns = np.zeros(num_simulations)
    for i in range(num_simulations):
        random_returns = np.random.normal(
            average_daily_return, volatility, forecast_days
        )
        cumulative_return = np.prod(1 + random_returns)
        simulated_end_returns[i] = initial_investment * cumulative_return

    # Calculate the final investment values
    final_investment_values = simulated_end_returns

    # Calculate Value at Risk (VaR) and Expected Tail Loss (Conditional VaR)
    confidence_level = 0.95
    sorted_returns = np.sort(final_investment_values)
    index_at_var = int((1 - confidence_level) * num_simulations)
    var = initial_investment - sorted_returns[index_at_var]
    conditional_var = initial_investment - sorted_returns[:index_at_var].mean()

    print(f"Value at Risk (95% confidence): £{var:,.2f}")
    print(f"Expected Tail Loss (Conditional VaR): £{conditional_var:,.2f}")

    num_success = np.sum(
        final_investment_values >= initial_investment * (1 + desired_return)
    )
    probability_of_success = num_success / num_simulations

    print(
        f"Probability of achieving at least a {desired_return*100}% return: {probability_of_success*100:.2f}%"
    )

    plt.figure(figsize=(10, 6))
    plt.hist(final_investment_values, bins=50, alpha=0.75)
    plt.axvline(
        initial_investment * (1 + desired_return),
        color="r",
        linestyle="dashed",
        linewidth=2,
    )
    plt.axvline(initial_investment - var, color="g", linestyle="dashed", linewidth=2)
    plt.title("Distribution of Final Investment Values")
    plt.xlabel("Final Investment Value")
    plt.ylabel("Frequency")
    plt.show()

    """
    # Plotting the results
    plt.figure(figsize=(10, 6))
    plt.plot(simulations.T, color="blue", alpha=0.025)
    plt.title("Monte Carlo Simulation of Future Prices")
    plt.xlabel("Day")
    plt.ylabel("Price")
    plt.show()
    """

레퍼런스

2024년 3월 22일 금요일

무료 LiDAR 포인트 클라우드 다운로드 웹사이트 소개

이 글은 무료 LiDAR(라이다) 포인트 클라우드 제공 다운로드 웹사이트를 간략히 소개한다. 


OpenTopography
OpenTopography는 지구 과학 연구와 교육을 위해 고해상도 지형 데이터를 액세스하고 활용할 수 있는 플랫폼이다. 이 웹사이트에서는 뉴질랜드의 라이다 데이터와 관련된 새로운 데이터셋도 제공하고 있다.

USGS Earth Explorer
USGS Earth Explorer는 위성, 항공기 및 기타 원격 감지 데이터를 검색, 발견 및 주문할 수 있는 웹 응용 프로그램이다. 지리 정보 시스템(GIS) 전문가, 연구원 및 교육자들이 이 웹사이트를 활용하여 지구 환경에 대한 데이터를 탐색하고 활용할 수 있다.

The United States Interagency Elevation Inventory
이 웹사이트는 미국 및 그 영토에 대한 고정밀 지형 및 해저 지형 데이터를 제공하는 국가 간 고도 인벤토리이다. 이러한 데이터는 연구, 환경 관리 및 재난 대응에 활용된다.

NOAA Digital Coast
NOAA Digital Coast는 연안 문제를 해결하기 위해 필요한 데이터, 도구 및 교육을 제공하는 웹 플랫폼이다. 연안 지역의 환경, 생태계 및 공간 정보를 탐색하고 활용할 수 있다.

National Ecological Observatory Network (NEON)
NEON은 미국 내의 다양한 위치에서 생태학적 및 기후학적 관측을 수행하는 네트워크이다. 이러한 데이터는 지속적인 연구와 교육에 활용된다.

Equator LIDAR Data Online
Equator는 LIDAR 데이터를 제공하는 플랫폼이다. 이 웹사이트에서는 다양한 지역의 지형 데이터를 탐색하고 활용할 수 있다.

레퍼런스

2024년 3월 21일 목요일

허깅페이스 트랜스포머 라이브러리 사용법 총정리

이 글은 그 동안 틈틈히 사용했었던 허깅페이스 트랜스포머 라이브러리 사용법을 총정리해본다. 이 글은 QA 시스템, 문장 분류, 토큰 의미 예측 방법 등을 소개한다. 이 글은 생성AI의 핵심 아키텍처 모델인 트랜스포머를 잘 이용하고 싶은 개발자, 연구자, 학생들에게 도움이 된다. 

만약, 트랜스포머의 내부 동작 메커니즘이 궁금하다면, 다음 링크를 참고한다.

소개
허깅페이스는 트랜스포머 라이브러리를 개발하여, 관련 최신 모델을 다운로드하고, 쉽게 학습 및 사용할 수 있는 API 도구를 제공한다. 

트랜스포머를 통해 다음 기능을 구현할 수 있다. 
훈련 데이터셋 다운로드 제공 예(yelp_review_full · Datasets at Hugging Face)


지원되는 모델
아래 표를 보면 알겠지만, LLM(Large Language Model) 뿐 아니라 생성AI와 관련된 모든 사전 학습된 모델을 제공한다(상세 참고). 
라이브러리 설치 방법
이 라이브러리 사용을 위해서는 NVIDIA GPU, CUDA, PyTorch, Tensorflow 사전 설치가 필요하다. 
명령행 터미널을 실행하고, 가상환경에서 다음을 입력해, 라이브러리를 설치한다.
pip install transformers[torch] datasets evaluate

설치하면, 추론 inference 등에 사용할 수 있는 파이프라인 객체를 사용할 수 있다. 파이프라인은 대부분 학습된 모델의 복잡성을 간소화한 API를 제공한다. 인식, 마스킹 언어 모델링, 특징 추출이 가능하다. 다음 코드는 그 예이다. 
import transformers, torch
from transformers import pipeline

print(transformers.__version__)
print(torch.cuda.is_available())

pipe = pipeline("text-classification", model="nlptown/bert-base-multilingual-uncased-sentiment", device=0)
msg = pipe("This restaurant is awesome")
print(msg)

다음과 같이 출력되면 성공한 것이다. 

트러블슈팅
현재 시점에서 텐서플로우 GPU버전은 패키지 의존성 에러가 발생한다. 참고로, pipeline에서 model과 device=0를 명시하면, 파이토치 GPU 버전으로 실행된다. 

방화벽으로 인해 오프라인 환경에서 실행해야 한다면 다음과 같이 설정 후 실행한다.
HF_DATASETS_OFFLINE=1 TRANSFORMERS_OFFLINE=1 \
python examples/pytorch/translation/run_translation.py --model_name_or_path google-t5/t5-small --dataset_name wmt16 --dataset_config ro-en ...

질의 응답 자료 학습
ChatGPT와 같이 질의 응답 자료를 학습 해본다. 학습된 모델은 허깅페이스의 허브에 저장해 놓고 재활용하기로 한다. 이를 위해, 다음과 같이 허깅페이스 토큰을 생성한다. 


이제, 다음과 같이 하습 데이터셋 다운로드 코딩한다. 
from huggingface_hub import notebook_login  # 허깅페이스 모델 업로드 위한 임포트
notebook_login()

from datasets import load_dataset  # squad 데이터셋 다운로드
squad = load_dataset("squad", split="train[:5000]")
squad = squad.train_test_split(test_size=0.2)
print(squad['train'][0])

다음과 같이 토크나이저에 훈련 텍스트 입력 처리를 위해, 최대 길이를 절단하는 등의 처리 함수를 코딩한다.
from transformers import AutoTokenizer  #  distilbert 토큰나이저 임포트
tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased") 

def preprocess_function(examples):
    questions = [q.strip() for q in examples["question"]]
    inputs = tokenizer(
        questions,
        examples["context"],
        max_length=384,
        truncation="only_second",
        return_offsets_mapping=True,
        padding="max_length",
    )

    offset_mapping = inputs.pop("offset_mapping")
    answers = examples["answers"]
    start_positions = []
    end_positions = []

    for i, offset in enumerate(offset_mapping):
        answer = answers[i]
        start_char = answer["answer_start"][0]
        end_char = answer["answer_start"][0] + len(answer["text"][0])
        sequence_ids = inputs.sequence_ids(i)

        # Find the start and end of the context
        idx = 0
        while sequence_ids[idx] != 1:
            idx += 1
        context_start = idx
        while sequence_ids[idx] == 1:
            idx += 1
        context_end = idx - 1

        # If the answer is not fully inside the context, label it (0, 0)
        if offset[context_start][0] > end_char or offset[context_end][1] < start_char:
            start_positions.append(0)
            end_positions.append(0)
        else:
            # Otherwise it's the start and end token positions
            idx = context_start
            while idx <= context_end and offset[idx][0] <= start_char:
                idx += 1
            start_positions.append(idx - 1)

            idx = context_end
            while idx >= context_start and offset[idx][1] >= end_char:
                idx -= 1
            end_positions.append(idx + 1)

    inputs["start_positions"] = start_positions
    inputs["end_positions"] = end_positions
    return inputs

데이터셋을 앞의 정의된 함수로 전처리한다. 필요하지 않은 열은 제거한다. 
tokenized_squad = squad.map(preprocess_function, batched=True, remove_columns=squad["train"].column_names)

학습을 위해 배치를 만든다. 
from transformers import DefaultDataCollator
data_collator = DefaultDataCollator()

from transformers import AutoModelForQuestionAnswering, TrainingArguments, Trainer
model = AutoModelForQuestionAnswering.from_pretrained("distilbert/distilbert-base-uncased")  # 사전 학습 모델을 파인튜닝한다

training_args = TrainingArguments(
    output_dir="my_awesome_qa_model",
    evaluation_strategy="epoch",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=3,
    weight_decay=0.01,
    push_to_hub=True,
)  # 학습될 모델 및 파라메터 명시

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_squad["train"],
    eval_dataset=tokenized_squad["test"],
    tokenizer=tokenizer,
    data_collator=data_collator,
)  # 전이학습모델, 파라메터, 데이터셋, 토크나이져, 배치처리를 위한 데이터 컬렉터 설정

trainer.train()  # 학습
trainer.push_to_hub()  # 학습된 데이터를 허브에 업로드

그 결과 다음과 같이 파인 튜닝된 학습 모델이 허브에 업로드되었다. 

다음과 같이 실행한다.
from transformers import pipeline

question = "How many programming languages does BLOOM support?"
context = "BLOOM has 176 billion parameters and can generate text in 46 languages natural languages and 13 programming languages."

question_answerer = pipeline("question-answering", model="my_awesome_qa_model")
question_answerer(question=question, context=context)

결과가 다음과 같다면 성공한 것이다.

NER(Named Entity Recognition) BERT 모델 파인튜닝
각 문장의 토큰 엔티티 의미를 인식하는 모델을 NER이라 한다. 문장 토큰의 의미를 인식할 수 있다면, 문장에서 특정 토큰에 대한 의미를 알고, 해당 의미에 대한 에이전트를 자동 실행하는 등의 서비스를 쉽게 개발할 수 있다. 

코드 개발 전에 다음을 설치한다. 
pip install transformers[torch] datasets

이 예제는 NER 데이터셋을 다운로드하고, BERT-BASE-NER(참고) 사전학습모델을 이용해 파인튜닝한다. BERT-BASE-NER 모델 사용방법은 다음과 같다. 
from transformers import AutoTokenizer, AutoModelForTokenClassification
from transformers import pipeline

tokenizer = AutoTokenizer.from_pretrained("dslim/bert-base-NER")
model = AutoModelForTokenClassification.from_pretrained("dslim/bert-base-NER")

nlp = pipeline("ner", model=model, tokenizer=tokenizer)
example = "My name is Wolfgang and I live in Berlin"

ner_results = nlp(example)
print(ner_results)

파인튜닝 데이터셋은 희귀한 토큰 의미를 정의한 데이터셋이다. 
NER 의미는 다음과 같다. 
Person
Location (including GPE, facility)
Corporation
Consumer good (tangible goods, or well-defined services)
Creative work (song, movie, book, and so on)
Group (subsuming music band, sports team, and non-corporate organisations)

이는 코드 상해 좀 더 상세화되어 표현되었다.
0: O
1: B-corporation
2: I-corporation
3: B-creative-work
4: I-creative-work
5: B-group
6: I-group
7: B-location
8: I-location
9: B-person
10: I-person
11: B-product
12: I-product

각 B, I, O는 Begin location, Inside location, Outside를 의미한다(NER 연구에 자주 나오는 용어). 참고로, New York City is a bustling metropolis의 NER 해석은 다음과 같다. 
New: O (Outside of any named entity)
York: B-LOC (Beginning of a Location entity)
City: I-LOC (Inside of a Location entity)
is: O
a: O
bustling: O
metropolis: O 

사용된 데이터셋은 다음과 같이 문장 토큰에 대한 NER이 정의되어 있다. 

이제, 다음 파인튜닝 코드를 입력해 실행, 학습한다. 
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("dslim/bert-base-NER")
def tokenize_and_align_tags(records):
    # 입력 단어를 토큰으로 분리함. 예를 들어, ChatGPT경우, ['Chat', '##G', '##PT']로 분해
    tokenized_results = tokenizer(records["tokens"], truncation=True, is_split_into_words=True)
    input_tags_list = []

    for i, given_tags in enumerate(records["ner_tags"]):
        word_ids = tokenized_results.word_ids(batch_index=i)
        previous_word_id = None
        input_tags = []

        for wid in word_ids:
            if wid is None:
                input_tags.append(-100)
            elif wid != previous_word_id:
                input_tags.append(given_tags[wid])
            else:
                input_tags.append(-100)
            previous_word_id = wid

        input_tags_list.append(input_tags)

    tokenized_results["labels"] = input_tags_list
    return tokenized_results

from datasets import load_dataset
wnut = load_dataset('wnut_17')
tokenized_wnut = wnut.map(tokenize_and_align_tags, batched=True)
tag_names = wnut["test"].features[f"ner_tags"].feature.names
id2label = dict(enumerate(tag_names))
label2id = dict(zip(id2label.values(), id2label.keys()))

from transformers import AutoModelForTokenClassification
model = AutoModelForTokenClassification.from_pretrained(
    "dslim/bert-base-NER", num_labels=len(id2label), id2label=id2label, label2id=label2id, ignore_mismatched_sizes=True
)

from transformers import Trainer, TrainingArguments, DataCollatorForTokenClassification
training_args = TrainingArguments(
    output_dir="my_finetuned_wnut_model",
)
''' # 하이퍼파라메터 튜닝용
training_args = TrainingArguments(
    output_dir="my_finetuned_wnut_model_1012",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=2,
    weight_decay=0.01,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
    push_to_hub=True,
)'''
data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer)     
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_wnut["train"],
    eval_dataset=tokenized_wnut["test"],
    tokenizer=tokenizer,
    data_collator=data_collator,
)

trainer.train()

from transformers import pipeline
model = AutoModelForTokenClassification.from_pretrained("my_finetuned_wnut_model/checkpoint-1000")
tokenizer = AutoTokenizer.from_pretrained("my_finetuned_wnut_model/checkpoint-1000")

classifier = pipeline("ner", model=model, tokenizer=tokenizer)
out = classifier("My name is Sylvain and I work at Hugging Face in Brooklyn.")
print(out)

import evaluate
seqeval = evaluate.load("seqeval")
results = trainer.evaluate()
print(results)
trainer.push_to_hub()

실행 결과는 다음과 같다. 

다음과 같이 문장 각 토큰의 의미(예. 사람, 위치 등)를 높은 정확도로 제공해 준다. 

마무리
이 글은 허깅페이스 트랜스포머를 이용해 다양한 사전학습 모델을 이용해 여러가지 서비스 개발 방법을 살펴보았다. 자체 데이터로 학습하거나, 데이터 학습을 좀 더 많이 할 수록 결과가 더 정확하고, 전문적이며, 풍부해 질 것이다.

레퍼런스

2024년 3월 16일 토요일

GPU 없는 로컬에서 서비스 가능한 경량 소형 LLM, LLAMA2.c 빌드, 실행, 학습 및 코드 분석하기

이 글은 GPU 없는 컴퓨터에서 경량 LLAMA2.c (라마씨)를 빌드하고, 로컬에서 실행, 학습하는 방법을 간략히 따라해 본다.
LLAMA2.c

머리말
앞서 설명한 코드 라마2는 최소 28GB이상의 GPU RAM이 필요하다. 많은 개발자의 경우, 현재 시점에서 이 정도 수준의 GPU 스펙 장비를 가진 경우는 매우 드물다. CoLab의 경우 T4 GPU는 16GB 크기를 가진다. 그러므로, 이를 해결할 수 있는 솔류션이 개발되었다. 

LLAMA2.c는 OpenAI 엔지니어인 Andrej Karpathy가 개발한 라마2를 이용한 소형 LLM 오픈소스 프로젝트이다. 이 라마 코드는 순수 C로 개발되었으며, 모델은 겨우 100MB로 동작되어, GPU가 없는 로컬 PC에서도 가볍게 실행된다. 

LLAMA.c 설치
설치, 실행 및 학습 방법은 다음과 같다. 터미널에서 다음 명령을 실행한다.
cd llama2.c
wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin

이 결과, https://huggingface.co/datasets/roneneldan/TinyStories 으로 학습된 모델이 다운로드된다.

실행하기
코드를 컴파일하고, 다운로드받은 스토리 학습 모델을 실행한다. 
make run
./run stories15M.bin

실행 결과는 다음과 같다. 텍스트가 잘 생성되는 것을 확인할 수 있다.

좀 더 큰 모델을 다운받아 실행해 본다.
wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories42M.bin
./run stories42M.bin
./run stories42M.bin -t 0.8 -n 256 -i "One day, Lily met a Shoggoth"


다음과 같이, 접두어, 추가 명령줄 인수를 지정할 수도 있다.
-t: 생성 온도. 0~1.0
 
데이터 학습 방법
새로운 데이터 훈련을 위해서는 앞에서 사용한 스토리 모델이 어떻게 학습되었는지 확인해 볼 필요가 있다. 그 방법은 다음과 같다.
python tinystories.py download
python tinystories.py pretokenize
python train.py

학습 데이터 다운로드 화면 일부

이제 컴파일을 한다. 
make run

다음과 같이 실행하면 된다. 
./run stories15M.bin

코드 및 학습 데이터 분석하기
LLAMA2.c의 구조는 매우 간단한데, make파일을 분석해 보면 단 하나의 run.c를 컴파일해 실행파일을 빌드하는 것을 확인할 수 있다.
gcc -O3 -o run run.c -lm

run.c의 주요 부분을 살펴보면 다음과 같다. 
typedef struct {
    // token embedding table
    float* token_embedding_table;    // (vocab_size, dim)
    // weights for rmsnorms
    float* rms_att_weight; // (layer, dim) rmsnorm weights
    float* rms_ffn_weight; // (layer, dim)
    // weights for matmuls. note dim == n_heads * head_size
    float* wq; // (layer, dim, n_heads * head_size)
    float* wk; // (layer, dim, n_kv_heads * head_size)
    float* wv; // (layer, dim, n_kv_heads * head_size)
    float* wo; // (layer, n_heads * head_size, dim)
    // weights for ffn
    float* w1; // (layer, hidden_dim, dim)
    float* w2; // (layer, dim, hidden_dim)
    float* w3; // (layer, hidden_dim, dim)
    // final rmsnorm
    float* rms_final_weight; // (dim,)
    // (optional) classifier weights for the logits, on the last layer
    float* wcls;
} TransformerWeights;

이 구조체의 이름은 TransformerWeights이며, 이는 Transformer 모델의 가중치를 저장하는 데 사용된다. 트랜스포머의 어텐션 스코어를 계산하는 데 핵심적인 자료구조이다. 각 필드는 다음과 같은 의미를 가진다:
  • token_embedding_table: 토큰 임베딩 테이블을 나타낸다. 이는 어휘 크기(vocab_size)와 차원(dim)의 2차원 배열이다.
  • rms_att_weight, rms_ffn_weight: RMSNorm의 가중치를 나타낸다. 각각 attention과 feed-forward network에 대한 것이다.
  • wq, wk, wv, wo: 각각 query, key, value, output에 대한 가중치를 나타낸다. 이들은 multi-head attention에서 사용된다.
  • w1, w2, w3: feed-forward network에서 사용되는 가중치이다.
  • rms_final_weight: 최종 RMSNorm의 가중치를 나타낸다.
  • wcls: (선택적으로) 마지막 레이어에서 로짓에 대한 분류기 가중치를 나타낸다.
  • 이 구조체는 Transformer 모델의 가중치를 저장하고 관리하는 데 사용된다.
전체적인 프로그램 실행 구조는 다음과 같다. 

1. 이 코드는 트랜스포머 모델의 구성, 가중치 및 상태에 대한 구조와 메모리 할당, 메모리 해제 및 체크포인트 읽기 기능을 정의한다.
2. 'rmsnorm', 'softmax', 'matmul'과 같은 신경망 블록을 위한 함수도 포함되어 있다.
3. 코드는 Transformer 모델을 통해 입력 토큰을 처리하여 출력 로짓을 생성하는 'forward' 함수를 구현한다.
4. 또한 BPE(Byte Pair Encoding) 토크나이저가 문자열을 토큰으로 또는 그 반대로 변환하는 구조와 함수가 있다.
5. 코드에는 argmax, 샘플링 및 top-p 샘플링과 같은 다양한 전략을 사용하여 확률을 기반으로 토큰을 샘플링하는 '샘플러' 구조와 함수가 포함된다.
6. 시간 측정을 위한 유틸리티 기능과 Transformer 모델을 기반으로 텍스트를 생성하는 '생성' 기능을 정의한다.
7. 마지막으로 트랜스포머 모델을 사용하여 사용자와 어시스턴트 간의 대화를 시뮬레이션하는 '채팅' 기능을 정의한다.  
전체 프로그램 구조도

앞에서 사용된 1.5GB가 넘는 스토리 학습 데이터의 구조는 다음과 같이 되어 있다.
학습 데이터 구조 일부

이를 본인의 목적에 맞게 적절히 데이터를 준비한 후, 다음과 같이 동일한 방식으로 학습하면 가중치 벡터가 저장된 bin파일을 얻을 수 있다. 이를 이용해, 앞서 언급된 방식과 동일하게 사용하면 된다.

레퍼런스

2024년 3월 13일 수요일

오픈소스 기반 프로젝트 문서, 버전 및 지식 관리 도구 소개

이 글은 무료로 사용할 수 있는 오픈소스 기반 프로젝트 문서, 버전, 지식 관리 도구들을 조사하고, 이를 간략히 나눔한다. 일부는 github에 공개되어 있어, 이를 잘 이용하면, 프로젝트 작업 프로세스에 통합 등을 할 수 있다.

프로젝트 문서 관리 도구 예시

웹 기반 파일 폴더 관리 도구
이 도구는 MIT라이센스에 따라 출시된 파일 관리자이다. 드래그앤드롭을 지원하며, AWS S3, 위지윅 편집기, 웹 기반 UI 지원한다. 

이 도구는 파일 관리 UI를 제공해, 파일 업로드, 삭제, 미리보기, 이름변경 및 편집을 지원하다. 독립 실행형 앱으로 사용할 수 있다.
이 도구는 SFTP, FTP, S3, GIT, LDAP, MYSQL등 지원하는 웹 파일 관리자이다. 이 도구는 인증, 공유, 미디어 재생 등을 지원한다. 모바일 친화적이고, 플러그인으로 확장이 가능하다.
웹용 파일 관리자이다. 직접 웹사이트 개발이 가능하다. 리눅스, 윈도우, 맥을 지원하고, 로컬 혹은 온라인 실행 가능하다. PHP5로 개발되었다.

서버 모든 폴더를 관리할 수 있는 웹 기반 PHP 파일 관리자이다. 웹 브라우저 기반 파일, 폴더 저장, 업로드 및 관리할 수 있다. PHP 5.5+ 로 개발되었다. 
React 기반 웹 브라우저 파일 관리 도구이다. 드래그앤드롭, 미리보기, 그리드 파일 보기 등을 지원한다. 
이 도구는 파일, 폴더를 관리하는 호스팅 웹 도구이다. 이 도구는 관리자, 사용자에게 개별 접근 권한, 역할을 부여할 수 있다. 대용량 파일 업로드를 지원한다.
이 도구는 Flask 서버를 사용해 WiFi, Internet 기반 파일 탐색 도구이다. 컴퓨터 전체 폴더를 탐색하고, 모든 파일을 다운로드 할 수 있다. 브라우저에서 비디오, 오디오 파일을 스트리밍할 수 있다.

문서 관리 시스템
파이썬 기반 Django를 사용해 개발된 문서 관리 시스템이다. 이 도구는 인텔, 대학 등 많은 기업에서 사용된다. 문서 워크플로 정의 기능을 지원한다.
이 도구는 클라우드 파일 공유 도구로, 멀티 플랫폼을 지원하며, 모바일도 지원한다. 백업, 복구 옵션이 있으며, 클라이언트 간 파일 동기화, 파일 잠금, 로깅, 암호화 등을 지원한다. 라즈베리파이에 설치 가능하다. 

NextCloud
이 도구는 모듈식으로 개발된 클라우드 파일 공유 도구로 GDPR를 준수하며, DICOM(Medical Imaging) 뷰어 앱을 제공한다. 이런 이유로, 의료 분야에 많이 사용된다. 이 도구로 부터 OwnCloud가 파생 개발되었다. 

실시간 협업, 버전 관리, 사용자 접근 관리, 문서 미리보기 및 승인, 워크플로 지원, 검색 등을 지원한다. 

자체 호스팅 지원하는 문서 관리 도구로, PHP로 개발되었고, 설치가 쉽다. 

Java로 개발된 도구이며, 기업용 오픈 소스 문서 관리 시스템이다. 

자체 호스팅을 지원하는 문서 관리 도구로, PHP로 개발되었다. MySQL을 사용하며, 파일 검토, 알림, 만료, 로깅, 리비전 기록 등을 지원한다. 메타 데이터 검색을 지원한다. 

버전 및 형상관리 
이 도구는 소스 분산 버전 관리 도구이다. 로컬 분기, 스테이징, 워크플로 등을 지원한다. 

소스 형상 관리 도구로 널리 사용되고 있다. 파일 및 문서 기록을 남기 있고, 여러 개발자가 동시 개발이 가능하다. 

멀티 플랫폼 지원하는 형상 관리 도구이다. 가볍고, 파이썬 애드온 등을 지원한다.

크로스 플랫폼을 지원하며, 부분 체크인, 아웃을 제공한다. 중앙 서버 유무에 관계없이 사용할수 있다.


지식 관리 도구
OpenKM은 스캔 이미지를 포함한 전자 문서를 저장, 추적, 관리 지원하는 지식관리 시스템이다. 대량 업로드, 오피스 추가 기능 등을 제공한다.
이 도구는 내외부 문서를 중앙 집중화하여, 정보를 검색하고, 문서에 레이블을 지정해 분류하는 데 도움을 준다.
이 도구는 팀, 지식을 연결하는 기능을 제공한다. 프로젝트 협업 시 유용한 기능을 제공한다.
이 도구는 고객의 질문, 답변을 관리해 지식 창고를 구축할 수 있는 기능을 제공한다. 

다음은 각 도구의 장단점을 보여준다.

쉐어포인트 대용 오픈소스 도구
이 도구는 사용자화 가능한 프로젝트 협업 메뉴를 제공한다. 쉐어포인트와 유사하게 동작하며, 문서 기반 협업이 용이하다. 워크플로, 아이디어 교환 등 기능을 제공한다.

이 도구는 Atlassian에서 개발한 협업 도구로, 중앙화된 작업 공간, 팀 작업 지원, 지식관리, 프로젝트 협업 등을 지원한다. 

이 도구는 메시징 기반 프로젝트 협업 도구로, 커뮤니케이션, 보이스 및 비디오 콜, 파일 공유, 작업 추적 등을 지원한다.

Jostle
이 도구는 인트라넷 서비스를 제공하여, 단순한 UI, 일정 공유, 파일 공유, 팀 협업, 조직도, 비디오 콜 등을 제공한다. 
전략 계획, 프로젝트 관리, 협업을 지원하는 도구로, KPI 추적, 리포트 생성, BSC 관리 등을 제공한다. 
이 도구는 프로젝트 관리, 비용 관리, 작업 추적 등을 지원한다. 

Classubes
이 도구는 세어포인트와 유사 기능을 제공하여, 문서 관리, 인트라넷, 일정 관리, 협업 등을 제공한다. 
이 도구는 협업 기능을 제공하며, 문서 기반 관리를 제공한다. 파일 공유, 작업 관리, 사용자화가 가능하다.

마무리
이외 다음과 같은 오픈소스 기반 문서 관리 도구가 있으니, 참고하기를 바란다. 
레퍼런스