Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yolov5
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Administrator
yolov5
Commits
70cb5650
提交
70cb5650
authored
2月 27, 2023
作者:
1051780106@qq.com
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
create: 注释
上级
4751345d
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
31 行增加
和
20 行删除
+31
-20
coco128.yaml
data/coco128.yaml
+3
-0
detect.py
detect.py
+0
-0
yolo.py
models/yolo.py
+2
-1
train.py
train.py
+0
-0
augmentations.py
utils/augmentations.py
+7
-6
dataloaders.py
utils/dataloaders.py
+9
-8
general.py
utils/general.py
+2
-2
torch_utils.py
utils/torch_utils.py
+8
-3
没有找到文件。
data/coco128.yaml
浏览文件 @
70cb5650
...
...
@@ -8,8 +8,11 @@
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
#数据集存放目录
path
:
../datasets/coco128
# dataset root dir
#训练集存放目录
train
:
images/train2017
# train images (relative to 'path') 128 images
#验证集存放目录
val
:
images/train2017
# val images (relative to 'path') 128 images
test
:
# test images (optional)
...
...
detect.py
浏览文件 @
70cb5650
差异被折叠。
点击展开。
models/yolo.py
浏览文件 @
70cb5650
...
...
@@ -163,7 +163,7 @@ class BaseModel(nn.Module):
class
DetectionModel
(
BaseModel
):
# YOLOv5 detection model
# YOLOv5 detection model
模型初始化
def
__init__
(
self
,
cfg
=
'yolov5s.yaml'
,
ch
=
3
,
nc
=
None
,
anchors
=
None
):
# model, input channels, number of classes
super
()
.
__init__
()
if
isinstance
(
cfg
,
dict
):
...
...
@@ -357,6 +357,7 @@ def parse_model(d, ch): # model_dict, input_channels(3)
if
__name__
==
'__main__'
:
# 定义参数信息
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'--cfg'
,
type
=
str
,
default
=
'yolov5s.yaml'
,
help
=
'model.yaml'
)
parser
.
add_argument
(
'--batch-size'
,
type
=
int
,
default
=
1
,
help
=
'total batch size for all GPUs'
)
...
...
train.py
浏览文件 @
70cb5650
差异被折叠。
点击展开。
utils/augmentations.py
浏览文件 @
70cb5650
...
...
@@ -110,21 +110,22 @@ def replicate(im, labels):
def
letterbox
(
im
,
new_shape
=
(
640
,
640
),
color
=
(
114
,
114
,
114
),
auto
=
True
,
scaleFill
=
False
,
scaleup
=
True
,
stride
=
32
):
# Resize and pad image while meeting stride-multiple constraints
shape
=
im
.
shape
[:
2
]
# current shape [height, width]
if
isinstance
(
new_shape
,
int
):
shape
=
im
.
shape
[:
2
]
# current shape [height, width]
原图的高和宽[h,w] (1080,810)
if
isinstance
(
new_shape
,
int
):
# 判断是不是int型的
new_shape
=
(
new_shape
,
new_shape
)
# Scale ratio (new / old)
# 按照新宽高/旧宽高 小的那一个,进行缩放
r
=
min
(
new_shape
[
0
]
/
shape
[
0
],
new_shape
[
1
]
/
shape
[
1
])
if
not
scaleup
:
# only scale down, do not scale up (for better val mAP)
r
=
min
(
r
,
1.0
)
# Compute padding
ratio
=
r
,
r
# width, height ratios
new_unpad
=
int
(
round
(
shape
[
1
]
*
r
)),
int
(
round
(
shape
[
0
]
*
r
))
dw
,
dh
=
new_shape
[
1
]
-
new_unpad
[
0
],
new_shape
[
0
]
-
new_unpad
[
1
]
# wh padding
if
auto
:
# minimum rectangle
dw
,
dh
=
np
.
mod
(
dw
,
stride
),
np
.
mod
(
dh
,
stride
)
# wh padding
new_unpad
=
int
(
round
(
shape
[
1
]
*
r
)),
int
(
round
(
shape
[
0
]
*
r
))
# 求出缩放后的宽高 [width,height] 新图的尺寸 (480,640)
dw
,
dh
=
new_shape
[
1
]
-
new_unpad
[
0
],
new_shape
[
0
]
-
new_unpad
[
1
]
# wh padding
160,0
if
auto
:
# minimum rectangle
最小矩形
dw
,
dh
=
np
.
mod
(
dw
,
stride
),
np
.
mod
(
dh
,
stride
)
# wh padding
如果满足32的倍数,自动填充,例如480为32倍数,所以padding就为0,dw=0,dh=0
elif
scaleFill
:
# stretch
dw
,
dh
=
0.0
,
0.0
new_unpad
=
(
new_shape
[
1
],
new_shape
[
0
])
...
...
utils/dataloaders.py
浏览文件 @
70cb5650
...
...
@@ -238,18 +238,18 @@ class LoadScreenshots:
class
LoadImages
:
# YOLOv5 image/video dataloader, i.e. `python detect.py --source image.jpg/vid.mp4`
def
__init__
(
self
,
path
,
img_size
=
640
,
stride
=
32
,
auto
=
True
,
transforms
=
None
,
vid_stride
=
1
):
def
__init__
(
self
,
path
,
img_size
=
640
,
stride
=
32
,
auto
=
True
,
transforms
=
None
,
vid_stride
=
1
):
# path:“data\\images\\bus.jpg”,img_size:[640,640]
if
isinstance
(
path
,
str
)
and
Path
(
path
)
.
suffix
==
'.txt'
:
# *.txt file with img/vid/dir on each line
path
=
Path
(
path
)
.
read_text
()
.
rsplit
()
files
=
[]
for
p
in
sorted
(
path
)
if
isinstance
(
path
,
(
list
,
tuple
))
else
[
path
]:
p
=
str
(
Path
(
p
)
.
resolve
())
if
'*'
in
p
:
p
=
str
(
Path
(
p
)
.
resolve
())
# 由相对路径得到绝对路径
if
'*'
in
p
:
# 判断路径是否带"*"号
files
.
extend
(
sorted
(
glob
.
glob
(
p
,
recursive
=
True
)))
# glob
elif
os
.
path
.
isdir
(
p
):
elif
os
.
path
.
isdir
(
p
):
# 判断路径是否是文件夹
files
.
extend
(
sorted
(
glob
.
glob
(
os
.
path
.
join
(
p
,
'*.*'
))))
# dir
elif
os
.
path
.
isfile
(
p
):
files
.
append
(
p
)
# files
elif
os
.
path
.
isfile
(
p
):
# 判断是不是文件
files
.
append
(
p
)
# files
, 变成列表形式
else
:
raise
FileNotFoundError
(
f
'{p} does not exist'
)
...
...
@@ -306,12 +306,13 @@ class LoadImages:
self
.
count
+=
1
im0
=
cv2
.
imread
(
path
)
# BGR
assert
im0
is
not
None
,
f
'Image Not Found {path}'
s
=
f
'image {self.count}/{self.nf} {path}: '
s
=
f
'image {self.count}/{self.nf} {path}: '
# 打印图片输出到第几张了
if
self
.
transforms
:
im
=
self
.
transforms
(
im0
)
# transforms
else
:
im
=
letterbox
(
im0
,
self
.
img_size
,
stride
=
self
.
stride
,
auto
=
self
.
auto
)[
0
]
# padded resize
# 将原图变成特定大小的图片,resize
im
=
letterbox
(
im0
,
self
.
img_size
,
stride
=
self
.
stride
,
auto
=
self
.
auto
)[
0
]
# padded resize (640,480,3)
im
=
im
.
transpose
((
2
,
0
,
1
))[::
-
1
]
# HWC to CHW, BGR to RGB
im
=
np
.
ascontiguousarray
(
im
)
# contiguous
...
...
utils/general.py
浏览文件 @
70cb5650
...
...
@@ -130,12 +130,12 @@ def set_logging(name=LOGGING_NAME, verbose=True):
name
:
{
'class'
:
'logging.StreamHandler'
,
'formatter'
:
name
,
'level'
:
level
,}},
'level'
:
level
,
}},
'loggers'
:
{
name
:
{
'level'
:
level
,
'handlers'
:
[
name
],
'propagate'
:
False
,}}})
'propagate'
:
False
,
}}})
set_logging
(
LOGGING_NAME
)
# run before defining LOGGER
...
...
utils/torch_utils.py
浏览文件 @
70cb5650
...
...
@@ -317,7 +317,9 @@ def copy_attr(a, b, include=(), exclude=()):
def
smart_optimizer
(
model
,
name
=
'Adam'
,
lr
=
0.001
,
momentum
=
0.9
,
decay
=
1e-5
):
# YOLOv5 3-param group optimizer: 0) weights with decay, 1) weights no decay, 2) biases no decay
# 把模型每一层的参数,划分到三个组中
g
=
[],
[],
[]
# optimizer parameter groups
# g[0]存所有卷积层的w参数,g[1] bn层的w,g[2]所有层的偏置项b
bn
=
tuple
(
v
for
k
,
v
in
nn
.
__dict__
.
items
()
if
'Norm'
in
k
)
# normalization layers, i.e. BatchNorm2d()
for
v
in
model
.
modules
():
for
p_name
,
p
in
v
.
named_parameters
(
recurse
=
0
):
...
...
@@ -327,7 +329,7 @@ def smart_optimizer(model, name='Adam', lr=0.001, momentum=0.9, decay=1e-5):
g
[
1
]
.
append
(
p
)
else
:
g
[
0
]
.
append
(
p
)
# weight (with decay)
# 判断训练过程中所使用的优化器的类型
if
name
==
'Adam'
:
optimizer
=
torch
.
optim
.
Adam
(
g
[
2
],
lr
=
lr
,
betas
=
(
momentum
,
0.999
))
# adjust beta1 to momentum
elif
name
==
'AdamW'
:
...
...
@@ -335,11 +337,12 @@ def smart_optimizer(model, name='Adam', lr=0.001, momentum=0.9, decay=1e-5):
elif
name
==
'RMSProp'
:
optimizer
=
torch
.
optim
.
RMSprop
(
g
[
2
],
lr
=
lr
,
momentum
=
momentum
)
elif
name
==
'SGD'
:
optimizer
=
torch
.
optim
.
SGD
(
g
[
2
],
lr
=
lr
,
momentum
=
momentum
,
nesterov
=
True
)
# 默认随机梯度下降法
optimizer
=
torch
.
optim
.
SGD
(
g
[
2
],
lr
=
lr
,
momentum
=
momentum
,
nesterov
=
True
)
# lr 学习率, momentum 动量值
else
:
raise
NotImplementedError
(
f
'Optimizer {name} not implemented.'
)
optimizer
.
add_param_group
({
'params'
:
g
[
0
],
'weight_decay'
:
decay
})
# add g0 with weight_decay
optimizer
.
add_param_group
({
'params'
:
g
[
0
],
'weight_decay'
:
decay
})
# add g0 with weight_decay
weight_decay标明要对卷积层的w进行权重衰减
optimizer
.
add_param_group
({
'params'
:
g
[
1
],
'weight_decay'
:
0.0
})
# add g1 (BatchNorm2d weights)
LOGGER
.
info
(
f
"{colorstr('optimizer:')} {type(optimizer).__name__}(lr={lr}) with parameter groups "
f
'{len(g[1])} weight(decay=0.0), {len(g[0])} weight(decay={decay}), {len(g[2])} bias'
)
...
...
@@ -369,10 +372,12 @@ def smart_resume(ckpt, optimizer, ema=None, weights='yolov5s.pt', epochs=300, re
ema
.
ema
.
load_state_dict
(
ckpt
[
'ema'
]
.
float
()
.
state_dict
())
# EMA
ema
.
updates
=
ckpt
[
'updates'
]
if
resume
:
# 如果resume有值,且开始轮数大于0则接着训练,否则,抛出异常
assert
start_epoch
>
0
,
f
'{weights} training to {epochs} epochs is finished, nothing to resume.
\n
'
\
f
"Start a new training without --resume, i.e. 'python train.py --weights {weights}'"
LOGGER
.
info
(
f
'Resuming training from {weights} from epoch {start_epoch} to {epochs} total epochs'
)
if
epochs
<
start_epoch
:
# 如果开始轮数大于epochs,会提示已训练了多少轮,接下来会用使用的轮数进行微调
LOGGER
.
info
(
f
"{weights} has been trained for {ckpt['epoch']} epochs. Fine-tuning for {epochs} more epochs."
)
epochs
+=
ckpt
[
'epoch'
]
# finetune additional epochs
return
best_fitness
,
start_epoch
,
epochs
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论