-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from lalala199812138/master
Add files via upload
- Loading branch information
Showing
5 changed files
with
407 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# %% | ||
from airtable import Airtable | ||
import pandas as pd | ||
|
||
base_id = 'app5x8nFdXg0Jj9JY' | ||
table_name = '评分' | ||
api_key = 'keyFvA03TJKPauBhh' | ||
|
||
AT = Airtable(base_id, table_name, api_key) | ||
print(AT) | ||
|
||
# %% | ||
view_name = 'Grid view' | ||
records = AT.get_all(view=view_name) | ||
|
||
df = pd.DataFrame.from_records((r['fields'] for r in records)) | ||
photos = df['房源照片'] | ||
ranks = df['平均评分'] | ||
|
||
# %% | ||
import requests | ||
|
||
def get_image(url, pic_name): | ||
response = requests.get(url) | ||
with open(pic_name, "wb") as fp: | ||
for data in response.iter_content(128): | ||
fp.write(data) | ||
|
||
# %% | ||
s = len(photos) | ||
for i in range(s): | ||
pic_name = './data/%04d.png'%i | ||
url = photos[i][0]['url'] | ||
get_image(url, pic_name) | ||
|
||
# %% | ||
with open('./data/label.txt', "w") as fopen: | ||
for i in range(s): | ||
pic_name = './data/%04d.png'%i | ||
fopen.write(pic_name) | ||
fopen.write('\t') | ||
fopen.write(str(ranks[i])) | ||
fopen.write('\n') | ||
|
||
|
||
# %% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# %% | ||
import cv2 | ||
|
||
src = cv2.imread('F:/rangduju/cnn-classification/data/0000.png', cv2.IMREAD_UNCHANGED) | ||
sw, sh, channels = src.shape | ||
dw = int(sw/5) | ||
dh = int(sh/5) | ||
#inter = cv2.INTER_LINEAR | ||
# 双线性插值。速度为最近邻和双三次的适中,效果也为二者适中。 | ||
inter = cv2.INTER_AREA | ||
# 区域插值,共分三种情况。图像放大时类似于双线性插值,图像缩小(x轴、y轴同时缩小)又分两种情况,均可避免波纹出现。 | ||
#inter = cv2.INTER_LANCZOS4 | ||
# 兰索斯插值。8*8,公式类似于双线性,计算量更大,效果更好,速度较慢。 | ||
#iner = cv2.INTER_NEAREST | ||
# 最近邻插值。因为没有插值,所以边缘会有严重的锯齿,放大后的图像有很严重的马赛克,缩小后的图像有很严重的失真。 | ||
#inter = cv2.INTER_CUBIC | ||
# 双三次插值。有效地避免出现锯齿现象,但速度最慢。放大时效果最好,但速度很慢。实际测试中并不慢,可能是优化的原因。 | ||
|
||
#dst = cv2.resize(src, (d_h, d_w), interpolation=inter) | ||
dst = cv2.resize(src, (0,0), fx=0.2, fy=0.2, interpolation=inter) | ||
cv2.imshow("dst",dst) | ||
cv2.waitKey(0) | ||
cv2.destroyAllWindows() | ||
# area插值效果最好,5种算法中只有area可以看清车牌并且没有车牌边缘没有出现波纹,其他都多少出现扭曲。 | ||
# %% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#%% | ||
import torch | ||
import torch.nn as nn | ||
import torch.nn.functional as F | ||
import torch.optim as optim | ||
from torchvision import datasets, transforms, models | ||
|
||
#%% | ||
torch.manual_seed(53113) | ||
|
||
use_cuda = torch.cuda.is_available() | ||
device = torch.device("cuda" if use_cuda else "cpu") | ||
batch_size = test_batch_size =32 | ||
kwargs = {'num_workers':0, 'pin_memory':True} if use_cuda else{} | ||
|
||
#%% | ||
train_loader = torch.utils.data.DataLoader( | ||
datasets.MNIST('./mnist_data', train=True, download=False, | ||
transform=transforms.Compose( | ||
[transforms.ToTensor(), | ||
transforms.Normalize((0.1307,),(0.3081,))])), | ||
batch_size=batch_size, shuffle=True,**kwargs | ||
) | ||
|
||
|
||
test_loader = torch.utils.data.DataLoader( | ||
datasets.MNIST('./mnist_data', train=False, download=False, | ||
transform=transforms.Compose( | ||
[transforms.ToTensor(), | ||
transforms.Normalize((0.1307,), (0.3081,))])), | ||
batch_size=test_batch_size, | ||
shuffle=True, **kwargs | ||
) | ||
|
||
#%% | ||
class Net(nn.Module): | ||
def __init__(self): | ||
super(Net, self).__init__() | ||
self.conv1 = nn.Conv2d(1, 20, 5, 1) | ||
self.conv2 = nn.Conv2d(20, 50, 5, 1) | ||
self.fc1 = nn.Linear(4*4*50, 500) | ||
self.fc2 = nn.Linear(500, 10) | ||
|
||
def forward(self, x): | ||
x = F.relu(self.conv1(x)) | ||
x = F.max_pool2d(x, 2, 2) | ||
x = F.relu(self.conv2(x)) | ||
x = F.max_pool2d(x, 2, 2) | ||
x = x.view(-1, 4*4*50) | ||
x = F.relu(self.fc1(x)) | ||
x = self.fc2(x) | ||
return F.log_softmax(x, dim=1) | ||
# forward和__init__要对齐,NotImplementedError是没有检测到forward | ||
# %% | ||
lr = 1e-3 | ||
momentum = 0.5 | ||
model = Net().to(device) | ||
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum) | ||
|
||
#%% | ||
def train(model, device, train_loader, optimizer, epoch, log_interval=100): | ||
model.train() | ||
for batch_idx,(data,target) in enumerate(train_loader): | ||
data, target = data.to(device), target.to(device) | ||
optimizer.zero_grad() | ||
output = model(data) | ||
loss = F.nll_loss(output, target) | ||
|
||
loss.backward() | ||
optimizer.step() | ||
if batch_idx % log_interval ==0: | ||
print("Train Epoch:{} [{}/{} ({:0f}%)]\tLoss:{:.6f}".format( | ||
epoch, | ||
batch_idx * len(data), | ||
len(train_loader.dataset), | ||
100.*batch_idx/len(train_loader), | ||
loss.item() | ||
)) | ||
|
||
#%% | ||
def test(model, devivce, test_loader): | ||
model.eval() | ||
test_loss = 0 | ||
correct = 0 | ||
with torch.no_grad(): | ||
for data, target in test_loader: | ||
data, target = data.to(devivce), target.to(devivce) | ||
output = model(data) | ||
test_loss +=F.nll_loss(output, target, reduction='sum').item() | ||
|
||
pred = output.argmax(dim=1, keepdim=True) | ||
correct +=pred.eq(target.view_as(pred)).sum().item() | ||
|
||
test_loss /= len(test_loader.dataset) | ||
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format( | ||
test_loss, correct, len(test_loader.dataset), | ||
100. * correct / len(test_loader.dataset))) | ||
|
||
# %% | ||
epochs = 2 | ||
for epoch in range(1, epochs + 1): | ||
train(model, device, train_loader, optimizer, epoch) | ||
test(model, device, test_loader) | ||
|
||
save_model = True | ||
if (save_model): | ||
torch.save(model.state_dict(),"mnist_cnn.pt") | ||
#词典格式,model.state_dict()只保存模型参数 | ||
|
||
# %% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
#%% | ||
import numpy as np | ||
import torch | ||
import torchvision | ||
import torch.nn as nn | ||
from torchvision import datasets, transforms, models | ||
import cv2 | ||
|
||
import matplotlib.pyplot as plt | ||
import time | ||
import os | ||
import copy | ||
print("Torchvision Version: ",torchvision.__version__) | ||
|
||
# %% | ||
# Top level data directory. Here we assume the format of the directory conforms | ||
# to the ImageFolder structure | ||
data_dir = "./hymenoptera_data" | ||
# Models to choose from [resnet, alexnet, vgg, squeezenet, densenet, inception] | ||
model_name = "resnet" | ||
# model_name = "alexnet" | ||
# model_name = "vgg" | ||
# Number of classes in the dataset | ||
num_classes = 2 | ||
# Batch size for training (change depending on how much memory you have) | ||
batch_size = 32 | ||
# Number of epochs to train for | ||
num_epochs = 15 | ||
# Flag for feature extracting. When False, we finetune the whole model, | ||
# when True we only update the reshaped layer params | ||
feature_extract = True | ||
|
||
input_size = 224 | ||
|
||
# %% | ||
all_imgs = datasets.ImageFolder(os.path.join(data_dir, "train"), transforms.Compose([ | ||
transforms.RandomResizedCrop(input_size), | ||
transforms.RandomHorizontalFlip(), | ||
transforms.ToTensor(), | ||
])) | ||
loader = torch.utils.data.DataLoader(all_imgs, | ||
batch_size=batch_size, | ||
shuffle=True, | ||
num_workers=4) | ||
|
||
# %% | ||
data_transforms = { | ||
"train": transforms.Compose([ | ||
transforms.RandomResizedCrop(input_size), | ||
transforms.RandomHorizontalFlip(), | ||
transforms.ToTensor(), | ||
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) | ||
]), | ||
"val": transforms.Compose([ | ||
transforms.Resize(input_size), | ||
transforms.CenterCrop(input_size), | ||
transforms.ToTensor(), | ||
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) | ||
]) | ||
} | ||
|
||
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ["train", "val"]} | ||
|
||
dataloaders_dict = {x: torch.utils.data.DataLoader(image_datasets[x], | ||
batch_size=batch_size, shuffle=True, num_workers=0) for x in ["train", "val"]} | ||
|
||
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | ||
|
||
# %% | ||
img = next(iter(dataloaders_dict["val"]))[0] | ||
print(img.shape) | ||
|
||
# %% | ||
''' | ||
unloader = transforms.ToPILImage() # reconvert into PIL image | ||
plt.ion() | ||
def imshow(tensor, title=None): | ||
image = tensor.cpu().clone() # we clone the tensor to not do changes on it | ||
image = image.squeeze(0) # remove the fake batch dimension | ||
image = unloader(image) | ||
plt.imshow(image) | ||
if title is not None: | ||
plt.title(title) | ||
plt.pause(0.001) # pause a bit so that plots are updated | ||
plt.figure() | ||
imshow(img[11], title='Image') | ||
''' | ||
|
||
# %% | ||
def set_parameter_requires_grad(model, feature_extract): | ||
if feature_extract: | ||
for param in model.parameters(): | ||
param.requires_grad = False | ||
|
||
def initialize_model(model_name, num_classes, feature_extract, use_pretrained=True): | ||
if model_name == "resnet": | ||
model_ft = models.resnet18(pretrained=use_pretrained) | ||
set_parameter_requires_grad(model_ft, feature_extract) | ||
num_ftrs = model_ft.fc.in_features | ||
model_ft.fc = nn.Linear(num_ftrs, num_classes) | ||
input_size = 224 | ||
|
||
elif model_name == "alexnet": | ||
model_ft = models.alexnet(pretrained=use_pretrained) | ||
set_parameter_requires_grad(model_ft, feature_extract) | ||
s = len(model_ft.classifier) - 1 | ||
num_ftrs = model_ft.classifier[s].in_features | ||
model_ft.classifier[s] = nn.Linear(num_ftrs, num_classes) | ||
input_size = 224 | ||
|
||
elif model_name == "vgg": | ||
model_ft = models.vgg19_bn() | ||
set_parameter_requires_grad(model_ft, feature_extract) | ||
s = len(model_ft.classifier) - 1 | ||
num_ftrs = model_ft.classifier[s].in_features | ||
model_ft.classifier[s] = nn.Linear(num_ftrs, num_classes) | ||
input_size = 224 | ||
|
||
else: | ||
print("model not implemented") | ||
return None, None | ||
|
||
return model_ft, input_size | ||
|
||
model_ft, input_size = initialize_model(model_name, | ||
num_classes, feature_extract, use_pretrained=True) | ||
print(model_ft) | ||
|
||
# %% | ||
def train_model(model, dataloaders, loss_fn, optimizer, num_epochs=5): | ||
best_model_wts = copy.deepcopy(model.state_dict()) | ||
best_acc = 0. | ||
val_acc_history = [] | ||
for epoch in range(num_epochs): | ||
for phase in ["train", "val"]: | ||
running_loss = 0. | ||
running_corrects = 0. | ||
if phase == "train": | ||
model.train() | ||
else: | ||
model.eval() | ||
|
||
for inputs, labels in dataloaders[phase]: | ||
inputs, labels = inputs.to(device), labels.to(device) | ||
|
||
with torch.autograd.set_grad_enabled(phase=="train"): | ||
outputs = model(inputs) # bsize * 2 | ||
loss = loss_fn(outputs, labels) | ||
|
||
preds = outputs.argmax(dim=1) | ||
if phase == "train": | ||
optimizer.zero_grad() | ||
loss.backward() | ||
optimizer.step() | ||
running_loss += loss.item() * inputs.size(0) | ||
running_corrects += torch.sum(preds.view(-1) == labels.view(-1)).item() | ||
|
||
epoch_loss = running_loss / len(dataloaders[phase].dataset) | ||
epoch_acc = running_corrects / len(dataloaders[phase].dataset) | ||
|
||
print("Phase {} loss: {}, acc: {}".format(phase, epoch_loss, epoch_acc)) | ||
|
||
if phase == "val" and epoch_acc > best_acc: | ||
best_acc = epoch_acc | ||
best_model_wts = copy.deepcopy(model.state_dict()) | ||
if phase == "val": | ||
val_acc_history.append(epoch_acc) | ||
model.load_state_dict(best_model_wts) | ||
return model, val_acc_history | ||
|
||
# %% | ||
model_ft = model_ft.to(device) | ||
optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, | ||
model_ft.parameters()), lr=0.001, momentum=0.9) | ||
loss_fn = nn.CrossEntropyLoss() | ||
# %% | ||
_, ohist = train_model(model_ft, dataloaders_dict, loss_fn, optimizer, num_epochs=num_epochs) | ||
|
||
# %% | ||
model_scratch, _ = initialize_model(model_name, | ||
num_classes, feature_extract=False, use_pretrained=False) | ||
model_scratch = model_scratch.to(device) | ||
optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, | ||
model_scratch.parameters()), lr=0.001, momentum=0.9) | ||
loss_fn = nn.CrossEntropyLoss() | ||
_, scratch_hist = train_model(model_scratch, dataloaders_dict, loss_fn, optimizer, num_epochs=num_epochs) | ||
|
||
save_model = True | ||
if (save_model): | ||
torch.save(model_scratch.state_dict(),"cnn_transfer.pt") | ||
# %% | ||
# Plot the training curves of validation accuracy vs. number | ||
# of training epochs for the transfer learning method and | ||
# the model trained from scratch | ||
|
||
plt.figure() | ||
plt.title("Validation Accuracy vs. Number of Training Epochs") | ||
plt.xlabel("Training Epochs") | ||
plt.ylabel("Validation Accuracy") | ||
plt.plot(range(1,num_epochs+1),ohist,label="Pretrained") | ||
plt.plot(range(1,num_epochs+1),scratch_hist,label="Scratch") | ||
plt.ylim((0,1.)) | ||
plt.xticks(np.arange(1, num_epochs+1, 1.0)) | ||
plt.legend() | ||
plt.show() |
Oops, something went wrong.