AWS RDS 사용 및 MySql-Workbench


AWS RDS

RDS -> 방화벽 인바운드 open ipv4 ipv6

RDS -> 파라미터 그룹 : 보안상의 이유로 Local 옵션을 금지하기 때문에 설정

RDS를 mysql workbench 연결 (연결 셋팅에서 OPT_LOCAL_INFILE=1기입)


MySQL Workbench 사용

RDS -> 나만의 Database -> table (csv참고해서) 생성 -> csv import 코드 -> 잘 올라갔는지


코랩에서 조회

selelct * from 테이블; -> 코랩에서 RDS 조회(이때, pymysql) -> ML 풀 프로세스



titanic 머신러닝

!pip install pymysql

mysql 연결

import pymysql
import pandas as pd

conn = pymysql.connect(
    host='database-1.chm3faoyztel.us-east-1.rds.amazonaws.com',
    user='',
    password='',
    database='nsdMLproject',
    charset='utf8mb4'
)

query='SELECT * FROM titanic;'
df = pd.read_sql(query, conn)
conn.close()


데이터 프레임에 값 잘 들어왔는지 확인

df.head(1)


# 데이터 파악
# Y에 널값은 있는지?(매우 위험)  x값에 널값은 있는지(처리하면됨)
df[['Pclass', 'Sex', 'Age', 'SibSp', 'Ticket', 'Fare','Survived']].info()


X, y 설정

# 2. X, y를 설정 - 문제 추가: x값 중에 문자 값이 있다. (y=survived, x=)
X = df[['Pclass', 'Sex', 'Age', 'SibSp', 'Ticket', 'Fare']]
y = df['Survived']


# 성별이 문자이므로 처리해야 한다.

# 방법1
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()

print(X.head(5)) # 어떤 걸로 바뀌었는지 확인하기 위해서.

X['Sex'] = le.fit_transform(X['Sex'])
print(X.head(5))


# 방법2
# X.loc[X['Sex'] == 'male', 'Sex'] = 1
# X.loc[X['Sex'] == 'female', 'Sex'] = 0


파생변수 만들기

# 1-1 전처리 1 [파생변수]
# Age에서 나이대라는 컬럼을 새로 추가
X['나이대'] = X['Age'].map(lambda x: x//10 * 10) #map mapping, 모든 행에 람다식을 매핑하겠다.

# Ticket을 정규표현식으로 수정. 순수한 숫자만 남긴다.
X['Ticket'] = X['Ticket'].str.extract(r'(\d+)')


train, valid 8:2 쪼개기

# 3. train, valid 8:2
from sklearn.model_selection import train_test_split
X_train, X_valid, y_train, y_valid = train_test_split(X,y, test_size = 0.2)


스케일링

# 리스케일링 할때 막 하면 안된다. 범주형이랑 연속형을 고려해야 한다. 연속성만 한다.
from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler()
X_train[['Age', 'Ticket', 'Fare']] = mms.fit_transform(X_train[['Age', 'Ticket', 'Fare']])
X_valid[['Age', 'Ticket', 'Fare']] = mms.transform(X_valid[['Age', 'Ticket', 'Fare']])


학습 및 추론

# 4. model 학습
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=1000) #옵션 값에 따라 성능이 너무 달라진다.
model.fit(X_train, y_train)


# 5. model 추론
from sklearn.metrics import f1_score
prediction = model.predict(X_valid)
f1_score(y_valid, prediction)


컴퓨터 마다 성능이 다른 경우,
모든 sklearn에는 데이터를 섞을때나, 모델의 weight나 랜덤으로 지정됨.

랜덤으로 숫자 뽑는 기분, 그걸 랜덤 시드라고 하고 고정을 random_state 로 함.
코랩에서 랜덤시드를 분명히 고정해놨는데 내일되니 똑같은 성능이 안나온다.


AWS S3

파일 업로드/다운로드

!pip install boto3


업로드

import boto3

# S3 클라이언트 생성
s3 = boto3.client(
    's3',
    aws_access_key_id='',         # 본인 키
    aws_secret_access_key='',     # 본인 시크릿 키
    region_name='us-east-1'                  # 버지니아
)

# 파일 업로드
s3.upload_file(
    Filename='nsd개고양이.zip',                 # 로컬 파일명 (a.zip)
    Bucket='mys3osh0510',                       # 버킷 이름
    Key='uploads/nsd개고양이.zip'                # S3 내 저장 경로
)

print("업로드 완료")


다운로드

import boto3

# S3 클라이언트 생성
s3 = boto3.client(
    's3',
    aws_access_key_id='',         # 본인 키
    aws_secret_access_key='',     # 본인 시크릿 키
    region_name='us-east-1'                  # 버지니아
)

# 파일 다운로드
s3.download_file(
    Filename='nsd개고양이.zip',                 # 로컬 파일명 (a.zip)
    Bucket='mys3osh0510',                       # 버킷 이름
    Key='uploads/nsd개고양이.zip'                # S3 내 저장 경로
)

print("다운로드 완료")


!unzip nsd개고양이.zip


import torch
import torchvision.models as models
import torchvision.transforms as T
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import os

class CustomDataset(Dataset):      # 데이터 클래스
    def __init__(self, root_dir, transform=None):
        self.root_dir = root_dir   # 데이터 폴더 경로
        self.transform = transform # 전처리
        self.classes = os.listdir(root_dir) # root_dir에 있는 dogs 와 cats 폴더를 리스트로 받음
        self.data = []
        for label in range(len(self.classes)):
            class_folder = os.path.join(root_dir, self.classes[label])
            for filename in os.listdir(class_folder):
                img_path = os.path.join(class_folder, filename)
                self.data.append((img_path, label))

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        img_path, label = self.data[idx]
        image = Image.open(img_path)
        if self.transform:
            image = self.transform(image)
        return image, label

data_dir = "."
batch_size = 32
transform = T.Compose([
    T.Resize((224, 224)),
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
train_dataset = CustomDataset(os.path.join(data_dir, 'training_set'), transform=transform)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_dataset = CustomDataset(os.path.join(data_dir, 'test_set'), transform=transform)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)


# torchvision에서 사전 학습한 모델을 가져온다.
# 스펙: input 224 x 224 3채널 /
model = models.resnext50_32x4d(pretrained=True)


# 모델의 fully connected 부분을 새롭게 정의함.
# model.fc.in_features 기존 인풋사이즈로 들어오고, 지금 내 데이터의 클래스 갯수로 아웃을 내는
# linear 층으로 바꿈
model.fc = torch.nn.Linear(model.fc.in_features, len(train_dataset.classes))

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)


criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for images, labels in train_loader:
        images, labels = images.to(device), labels.to(device)
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()

    print(f"Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(train_loader)}")

torch.save(model.state_dict(), 'resnet_model.pth')

model.eval()
correct = 0
total = 0
with torch.no_grad():
    for images, labels in test_loader:
        images, labels = images.to(device), labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs, 1) # 분류할 때, softmax를 써야 하는 게 일반적이나, 학습하면서 확률 값을 뱉는다.
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

accuracy = 100 * correct / total
print(f'Accuracy on test set: {accuracy}%')



댓글 쓰기

다음 이전