https://towardsdatascience.com/data-preprocessing-and-visualization-in-c-6d97ed236f3b
C++를 사용하여 기계 학습의 기본 기능을 구현하는 방법에 대한 동작 코드 예제
https://gist.github.com/ahmhashesh
“우리는 믿습니다. 모든 사람들은 데이터와 함께 해야 합니다.” — W. Edwards Deming, 통계학자, 교수, 저자, 강사 및 컨설턴트.
데이터 전처리는 원시 데이터를 컴퓨터가 이해할 수 있는 형식으로 변환하는 프로세스로 모든 기계 학습 작업의 첫 번째 단계입니다. 데이터 수집은 일반적으로 느슨하게 제어되며 값이 범위를 벗어날 수 있습니다. 데이터 준비 및 필터링 단계에는 상당한 처리 시간이 소요될 수 있습니다.
데이터 전처리가 포함하는 것들:
- 파일에서 데이터 읽기.
- 데이터 클리닝.
- 인스턴스 선택.
- 데이터 표준화.
- 데이터 변환.
- 특징 추출 및 선택.
자세한 내용은 다음 비디오를 참고 할 수 있습니다.
데이터 전처리의 결과물이 최종 훈련 세트가 됩니다. 이 기사에서는 C++를 사용하면서 일부 데이터 전처리 단계와 Matplotlib-Cpp 라이브러리를 사용한 데이터 시각화를 다룰 것입니다.
이 기사는 C++에서 기계 학습 알고리즘의 구현을 다루는 시리즈의 일부이며, 이 시리즈 전체에서 여기로부터 사용할 수 있는 Iris 데이터 세트를 사용할 것입니다.
- 언제 C++를 사용하여 기계 학습을 배워야 합니까?
- 모든 C++ 개발자가 읽어야 할 8권의 책.
- C++의 데이터 전처리 및 시각화.
- C++를 사용한 기계 학습 데이터 조작.
- C++를 사용하여 처음 부터 따라하는 Naive Bayes.
- C++에서 선형 회귀 구현.
이 작업을 쉽게 수행할 수 있는 라이브러리가 이미 있지만 이 시리즈의 목적은 이러한 알고리즘을 처음부터 개발하는 방법을 배우는 것입니다.
C++용 ML 라이브러리에 대해 자세히 알아보려면 다음 문서를 참조하세요:
https://www.analyticsvidhya.com/blog/2020/05/introduction-machine-learning-libraries-c/
이 기사에서는 iris 데이터 세트를 각 작업을 수행할 수 있는 데이터의 예로 사용할 것이며 이 튜토리얼에서는 C++11을 사용할 것이라는 점에 유의하십시오.
파일에서 데이터 읽기:
여기에서 iris.data 파일을 다운로드한 후. 간단한 파일 읽기 지침으로 파일에서 데이터를 읽고 별도의 벡터에서 각 데이터 유형을 구문 분석해 보겠습니다.
std::vector<std::vector<float>> Read_Iris_Dataset(void)
{
std::ifstream myfile("iris.data");
std::string line;
std::vector<std::vector<float>> Iris_Dataset;
std::vector<float> temp_sepal_len;
std::vector<float> temp_sepal_wid;
std::vector<float> temp_petal_len;
std::vector<float> temp_petal_wid;
std::vector<float> temp_iris_class;
float sepal_len_f,sepal_wid_f,petal_len_f,petal_wid_f;
float iris_class_f;
std::string temp_string;
int count =0;
if (myfile.is_open())
{
std::cout<< "file opened successfully"<<std::endl;
while (std::getline(myfile, line)) {
std::replace(line.begin(), line.end(), '-', '_');
std::replace(line.begin(), line.end(), ',', ' ');
std::istringstream iss(line);
count++;
iss >> sepal_len_f>>sepal_wid_f >> petal_len_f >>petal_wid_f >> temp_string;
temp_sepal_len.push_back(sepal_len_f);
temp_sepal_wid.push_back(sepal_wid_f);
temp_petal_len.push_back(petal_len_f);
temp_petal_wid.push_back(petal_wid_f);
if(temp_string.compare("Iris_setosa") == 0)
{
iris_class_f = Iris_setosa;
}
else if (temp_string.compare("Iris_versicolor") == 0)
{
iris_class_f = Iris_versicolor;
}
else if (temp_string.compare("Iris_virginica") == 0)
{
iris_class_f = Iris_virginica;
}else
{
iris_class_f = Iris_unkown;
}
temp_iris_class.push_back(iris_class_f);
}
Iris_Dataset.push_back(temp_sepal_len);
Iris_Dataset.push_back(temp_sepal_wid);
Iris_Dataset.push_back(temp_petal_len);
Iris_Dataset.push_back(temp_petal_wid);
Iris_Dataset.push_back(temp_iris_class);
}
else
{
std::cout << "Unable to open file";
}
return Iris_Dataset;
}
이 코드에서는 ifstream을 사용하여 파일에서 간단한 입력 스트림을 생성했습니다.
std::ifstream myfile("iris.data");
또한 여러 벡터를 사용하여 데이터 세트의 각 정보 유형을 읽은 다음 모든 데이터를 단일 2차원 벡터에 추가했습니다.
std::vector<std::vector<float>> Iris_Dataset;
std::vector<float> temp_sepal_len;
std::vector<float> temp_sepal_wid;
std::vector<float> temp_petal_len;
std::vector<float> temp_petal_wid;
std::vector<float> temp_iris_class;
...
temp_sepal_len.push_back(sepal_len_f);
temp_sepal_wid.push_back(sepal_wid_f);
temp_petal_len.push_back(petal_len_f);
temp_petal_wid.push_back(petal_wid_f);
...
Iris_Dataset.push_back(temp_sepal_len);
Iris_Dataset.push_back(temp_sepal_wid);
Iris_Dataset.push_back(temp_petal_len);
Iris_Dataset.push_back(temp_petal_wid);
iris 데이터셋에서 Iris_Dataset 벡터내에는 문자열 타입인 iris 클래스 데이터를 제외한 모든 데이터가 같은 데이터 타입이었기 때문에 이것을 enum 타입으로 변환하고 float로 처리하여 나머지 데이터와 일치시켜야 합니다.
하지만, 구조를 생성하고 여기에 데이터를 로드하거나 iris 데이터 세트에 대한 클래스를 생성하고 해당 클래스에 데이터를 로드하는 것과 같이 다른 유형으로 데이터를 로드하는 다른 방법을 항상 사용할 수 있습니다.
struct Iris {
float sepal_length;
float sepal_width;
float petal_length;
float petal_width;
std::string ir_class;
};
지금은 동일한 데이터 유형을 가진 데이터를 처리하는 이 간단한 방법을 진행하기로 결정했습니다.
데이터 시각화:
이미지는 말보다 더 중요합니다. 데이터를 시각적으로 표현하는 것은 데이터를 이해하고, 데이터에 대한 정보를 수집하고, 이상값을 식별하는 데 중요할 수 있습니다.
이것은 C++를 사용하여 기계 학습 알고리즘을 개발하는 데 덜 중요해 보이지만 대부분 알고리즘을 테스트하고 구현하기 위해 Python과 같은 다른 언어로 데이터를 사용하여 작업한 다음 알고리즘을 C++로 변환할 수 있기 때문에 이것이 중요할 수 있다고 생각합니다. 예를 들어 디버깅 목적으로 구현하는 동안 데이터를 시각화 하는 것입니다.
이 기사에서는 Matplotlib의 Python API에 대한 간단한 래퍼인 Matplotlib-CPP를 사용합니다. 라이브러리에 대한 자세한 내용은 설명서를 검토해 보십시오.
Matplotlib-CPP를 사용하는 것은 간단합니다. "matplotlibcpp.h" 헤더 파일을 포함하고 Python 라이브러리와 연결하기만 하면 됩니다. 다음은 GitHub 리포지토리의 최소 예입니다.
#include "matplotlibcpp.h"
namespace plt = matplotlibcpp;
int main() {
plt::plot({1,3,2,4});
plt::show();
}
std::vector<std::vector<float>> dataset = Read_Iris_Dataset();
...
plt::plot(dataset[0],{{"label", "sepal_length"}});
plt::plot(dataset[1],{ {"label", "sepal_width"}});
plt::plot(dataset[2],{ {"label", "petal_length"}});
plt::plot(dataset[3],{ {"label", "petal_width"}});
plt::title("Standard usage");
plt::legend();
plt::show();
bar API를 사용하여 데이터를 표현하는 또 다른 방법:
데이터 클리닝:
데이터 세트에서 손상되거나 부정확한 데이터를 감지하고 수정(또는 제거)하는 프로세스로 예를 들어, 데이터 수집 단계에서 일부 누락되거나 일관성 없는 값 또는 이상값이 발생할 수 있습니다.
이전 함수에서 일부 값을 바꾸기 위해 replace std::replace 함수를 사용했음을 알 수 있습니다. 이 단계는 데이터를 벡터로 읽기도 전에 값을 제거하거나 바꾸는 데 사용할 수 있습니다. 예를 들어 여기에서 "," 또는 "-"는 파일에서 값을 로드하는 데 혼동을 줄 수 있으므로 다른 값으로 대체하여 통일된 읽기 방법을 사용하기로 결정했습니다.
std::replace(line.begin(), line.end(), '-', '_');
std::replace(line.begin(), line.end(), ',', ' ');
또 다른 방법은 iterator 와 람다 식을 사용하여 벡터에 추가된 데이터를 제거하거나 교체하는 것입니다.
다음은 Sepal Length에서 5.8보다 큰 값을 제거한 예입니다.
이것은 한 줄의 코드를 추가하여 수행할 수 있습니다.
std::replace_if(dataset[0].begin(), dataset[0].end(), [](float &value) { return value >= 5.8;}, 5.8);
데이터 표준화:
데이터 표준화는 기계 학습 모델에서 모델 정확도를 향상시키는 중요한 단계입니다. 데이터 표준화의 중요성에 대해 자세히 알아보려면 다음 문서를 참조하세요:
데이터 세트를 표준화하려면 관찰된 값의 평균이 0이고 표준 편차가 1이 되도록 값의 분포를 다시 조정해야 합니다. 이렇게 하려면 평균을 빼고 표준 편차로 나누어야 합니다.
먼저 Mean을 계산하기 위한 API를 구현합니다:
template <typename T>
T Mean (std::vector<T> Data)
{
T mean = std::accumulate(std::begin(Data), std::end(Data), 0.0) / Data.size();
return mean;
}
이 API는 모든 표준 유형의 벡터를 사용하여 평균값을 계산 해 줄 것입니다. 유사한 것을 사용하여 표준 편차를 계산할 수 있습니다.
template <typename M>
double StDev (std::vector<M> &Data)
{
M mean = std::accumulate(std::begin(Data), std::end(Data), 0.0) / Data.size();
double sq_sum = std::inner_product(Data.begin(), Data.end(), Data.begin(), 0.0);
double stdev = std::sqrt(sq_sum / Data.size() - (double)(mean * mean));
return stdev;
}
꽃받침 길이의 평균 및 표준 편차 계산:
float sepal_length_mean = Mean(dataset[0]);
float sepal_length_stdev = StDev(dataset[0]);
표준화를 적용하기 전에 데이터를 시각화할 수 있습니다:
그런 다음 이 한 줄 코드를 적용하여 표준화 후 값을 계산할 수 있습니다:
std::for_each( dataset[0].begin(), dataset[0].end(), [&](float & x){ x = ((x - sepal_length_mean)/sepal_length_stdev);});
이 기사에서는 일부 데이터 전처리 단계의 구현 예에 대해서 생각해 보았으며, 파일에서 데이터 읽기, Matplotlibcpp를 사용한 데이터 정규화의 부분으로서의 데이터 시각화, 데이터 클리닝, 데이터에 대한 평균 및 표준 편차와 같은 일부 작업 수행을 소개 해 보았습니다.
추천 도서:
- The C++ Programming Language, by Bjarne Stroustrup
- The Hundred-Page Machine Learning Book, by Andriy Burkov
- Machine Learning For Absolute Beginners, by Oliver Theobald
또는 다음 자습서를 따라해 볼 수 있습니다.
또는 각 기계 학습 개발자가 읽어야 할 9권의 책 및 각 개발자가 읽어야 하는 8권의 C++ 프로그래밍 책에 대해 설명하는 이 기사를 읽어 보십시오.
이 기사는 C++에서 기계 학습 알고리즘의 구현을 다루는 시리즈의 일부이며, 이 시리즈 전체에서 여기에서 사용할 수 있는 Iris 데이터 세트를 사용할 것입니다.
이상.
'머신러닝' 카테고리의 다른 글
피드포워드 신경망으로 숫자 및 의류 항목 분류 (0) | 2023.04.17 |
---|---|
파이썬 코드 예제 - 초보자를 위한 머신러닝 알고리즘 (1) | 2023.04.05 |
선형회귀와 그래프 (0) | 2022.10.12 |
선형회귀에 대한 고찰 (2) | 2022.10.07 |
기계 학습 시각화에 대한 간단한 가이드 (0) | 2022.04.27 |