2.3 C3网络结构原理及代码解释

一,原理

原理的图片参考了P8:在天气识别中加入YOLOv5-C3模块_yolov5中c3个数_爱挠静香的下巴的博客-CSDN博客

C3网络构成如下图所示:

1.首先我们假设输入(input)一个tensor类型的float32的1X3X10X100的矩阵x;

2.Conv卷积网络结构:构建一个卷积网络,其输入通道为3,输出通道为3,卷积核大小为1,步长为1;再加标准化BatchNorm2d+激活函数SiLU;

3.Bottleneck残差网络结构:如下图,输入x后由两个卷积网络Conv得到一个1X3X10X100的矩阵y,这个矩阵y是对x的值经过标准化和激活函数处理过的输出值,矩阵大小和输入的x相同。最后返回值是x与y的和,即返回x+y,在这里残差网络就构建完了;

4.C3网络结构:将输入的x分别做两种处理,一是由残差网络获得一个输出值output1,二是直接由Conv卷积网络获得一个输出矩阵output2(注意,这里的conv内的输入和输出通道数会有所改变,具体变化可以看下面的代码)。最后再将两个输出值相加,即最终返回torch.cat(output1,output2)。

 

二,代码解释

C3代码的运行用到了卷积网络和残差网络,所以代码看着有点多,可以根据上面的原理思路一个一个理解。其代码解释如下:

import torch
import cv2
import numpy as np
import torch.nn as nn

#输入图片路径
image=cv2.imread(r"D:\AI\data\red_green_light\4.jpg")

images=image.reshape(1,3,1080, 1920)

input=torch.tensor(images,dtype=torch.float32)#浮点型


#silu激活函数
class SiLU(nn.Module):
    @staticmethod
    def forward(x):
        return x * torch.sigmoid(x)

def autopad(k, p=None):
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
    return p
#卷积结构
class Conv(nn.Module):
    def __init__(self, c1=3, c2=3, k=1, s=1, p=None, g=1, act=True):
        super(Conv, self).__init__()
        #卷积、标准化加激活函数
        self.conv   = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)#卷积
        self.bn     = nn.BatchNorm2d(c2, eps=0.001, momentum=0.03)#标准化
        self.act    = SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())#激活函数

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))#卷积->BatchNorm2d->激活函数->output

    def fuseforward(self, x):
        return self.act(self.conv(x))#这个forward函数不存在BN操作


#残差网络
class Bottleneck(nn.Module):
    # Standard bottleneck
    def __init__(self, c1=3, c2=3, shortcut=True, g=1, e=0.5):
        super(Bottleneck,self).__init__()
        c_=int(c2*e)# hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)  # 输入通道数为c1,输出通道数为c_,卷积核大小为1,步长为1,默认为0填充(实际上是图片本身)
        self.cv2 = Conv(c_, c2, 3, 1, g=g)  # 输入通道数为c_,输出通道数为c2,卷积核大小为3,步长为1,默认为0填充
        self.add=shortcut and c1==c2# c1与c2需相同才可进行shortcut运算

    def forward(self,x):
        # 根据self.add的值确定是否有shortcut
        return x+self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))


class C3(nn.Module):
    def __init__(self,c1=3, c2=3, n=1, shortcut=True, g=1, e=0.5):# ch_in, ch_out, number, shortcut, groups, expansion
        super(C3,self).__init__()
        c_=int(c2*e)
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # act=FReLU(c2)
        self.m=nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])

    def forward(self,x):
        return self.cv3(torch.cat(
            (
                self.m(self.cv1(x)),
                self.cv2(x)
            )
        ,dim=1))




#1.卷积网络
hh=Conv()
output2=hh(input)

#2.运用残差网络
ss=Bottleneck()
output=ss(input)

#3.运用C3网络
tt=C3()
out=tt(input)

print("输入值x",input)

print("卷积值:",output2)

print("残差值:",output)

print("C3值:",out)
print(out.shape)

<think>好的,用户想了解C#中的三维向量。首先,我需要确认三维向量的基本概念,确保自己理解正确。向量运算的一种,结果是一个垂直于原有两个向量的新向量,方向由右手定则决定,大小等于两个向量的模长以夹角的正弦值。 接下来要考虑在C#中如何表示三维向量。通常会用包含三个浮数(float或double)的结构体或类,比如Vector3。可能需要提到Unity的Vector3结构体,因为Unity是C#的常见应用场景,但用户可能没有使用Unity,所以也要说明如何自己实现。 然后,的公式是关键。三维向量ab的公式是: a × b = (a_y*b_z - a_z*b_y, a_z*b_x - a_x*b_z, a_x*b_y - a_y*b_x) 需要确保公式正确,并转换为LaTeX格式。用户提到系统级指令中数学公式要用$...$,所以得检查格式是否正确。 接下来,如何在C#中实现这个公式。可能需要写一个静态方法,接受两个Vector3参数,返回新的Vector3结果。代码示例要简洁,使用double类型,或者根据情况选择float。同时,是否需要处理特殊情况,比如零向量,但通常本身已经处理了这些情况,所以可能不需要额外处理。 然后,举例说明使用的实际例子,比如计算法向量,或者判断两个向量的相对方向。例如,在3D图形学中,常用于计算垂直于两个向量的方向,用于确定面的朝向。 还要注意的性质,比如反交换律a×b = -b×a,结果向量的模长等于面等,这些可能对用户有帮助,但用户可能更关注实现,所以可能需要简要提及。 用户可能的问题包括:如何验证的正确性,单位向量结果,或者如何处理向量的归一化。需要确保回答覆盖这些潜在,或者在示例中体现。 最后,检查代码是否符合C#语法,比如结构体的定义,方法的参数是否正确,返回值的计算是否准确。同时,是否需要处理异常,比如空引用,但结构体是值类型,所以可能不需要。 总结步骤:解释概念,给出公式,展示C#代码实现,提供示例输出,说明应用场景。确保符合用户的结构要求,分步骤清晰,代码正确,公式正确用LaTeX标注。</think>在C#中实现三维向量需要理解其数学定义,并通过代码正确表达。以下是逐步说明: 1. **数学定义** 三维向量$\vec{a} = (a_x, a_y, a_z)$$\vec{b} = (b_x, b_y, b_z)$的结果为: $$ \vec{a} \times \vec{b} = \left( a_y b_z - a_z b_y,\ a_z b_x - a_x b_z,\ a_x b_y - a_y b_x \right) $$ 结果向量垂直于$\vec{a}$$\vec{b}$构成的平面,方向由右手定则确定。 2. **C#实现步骤** - 定义三维向量结构体 ```csharp public struct Vector3 { public double X { get; } public double Y { get; } public double Z { get; } public Vector3(double x, double y, double z) { X = x; Y = y; Z = z; } } ``` - 实现方法 ```csharp public static Vector3 CrossProduct(Vector3 a, Vector3 b) { double x = a.Y * b.Z - a.Z * b.Y; double y = a.Z * b.X - a.X * b.Z; double z = a.X * b.Y - a.Y * b.X; return new Vector3(x, y, z); } ``` 3. **使用示例** ```csharp Vector3 v1 = new Vector3(1, 0, 0); // X轴单位向量 Vector3 v2 = new Vector3(0, 1, 0); // Y轴单位向量 Vector3 result = CrossProduct(v1, v2); Console.WriteLine($"Result: ({result.X}, {result.Y}, {result.Z})"); // 输出: (0, 0, 1) → Z轴单位向量 ``` 4. **应用场景** - 计算平面法向量(3D图形学) - 物理引擎中的扭矩计算 - 判断两个向量的相对方位(通过结果向量的方向) **验证性质** 可通过验证反交换律检查实现正确性: ```csharp CrossProduct(v1, v2) == -CrossProduct(v2, v1) // 应返回true ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值