当前位置: 首页 > news >正文

python训练营打卡第48天

随机函数与广播机制

知识点回顾:

  1. 随机张量的生成:torch.randn函数
  2. 卷积和池化的计算公式(可以不掌握,会自动计算的)
  3. pytorch的广播机制:加法和乘法的广播机制

ps:numpy运算也有类似的广播机制,基本一致

作业:

自己多借助ai举几个例子帮助自己理解即可

随机函数的应用示例:

import numpy as np# 1. 均匀分布随机数:生成3x3矩阵,数值在[0, 1)之间
uniform_data = np.random.uniform(size=(3, 3))
print("均匀分布随机数:\n", uniform_data)# 2. 正态分布随机数:均值0,标准差1,生成100个样本
normal_data = np.random.normal(loc=0, scale=1, size=100)
print("\n正态分布随机数均值:", np.mean(normal_data))  # 接近0# 3. 随机采样:从数组中不放回地抽取3个元素
arr = np.array([1, 2, 3, 4, 5])
sampled = np.random.choice(arr, size=3, replace=False)
print("\n随机采样结果:", sampled)# 4. 随机排列:打乱数组顺序
arr_shuffled = np.random.permutation(arr)  # 生成新数组,原数组不变
print("\n随机排列结果:", arr_shuffled)# 5. 随机种子:确保结果可复现
np.random.seed(42)  # 相同种子下,多次运行结果一致
print("\n设置种子后的均匀随机数:", np.random.uniform(size=3))    

输出结果:

1.均匀分布随机数:[[0.12155788 0.51018589 0.10955804][0.12604173 0.81162374 0.06650838][0.78791742 0.12684855 0.09960093]]2.正态分布随机数均值: -0.17274923180900453.随机采样结果: [1 3 2]4.随机排列结果: [1 4 2 5 3]5.设置种子后的均匀随机数: [0.37454012 0.95071431 0.73199394]

广播机制:

import numpy as np# 案例1:标量与二维数组运算
a = np.array([[1, 2], [3, 4]])
b = 2  # 标量
result = a * b  # 等价于每个元素×2
print("标量广播结果:\n", result)
# 输出:
# [[2 4]
#  [6 8]]# 案例2:一维数组与二维数组相加(列对齐)
c = np.array([10, 20, 30])  # 形状(3,)
d = np.array([[1, 2, 3], [4, 5, 6]])  # 形状(2, 3)
result = d + c  # c扩展为(2, 3)(行复制)
print("\n一维与二维相加结果:\n", result)
# 输出:
# [[11 22 33]
#  [14 25 36]]# 案例3:三维数组与二维数组相乘(维度扩展)
e = np.random.rand(2, 1, 4)  # 形状(2, 1, 4)
f = np.random.rand(3, 4)     # 形状(3, 4)
# 广播过程:f → (1, 3, 4) → (2, 3, 4),e → (2, 3, 4)
result = e * f  # 需确保最终形状兼容
print("\n三维与二维广播结果形状:", result.shape)  # 输出:(2, 3, 4)    

输出结果:

1.标量广播结果:[[2 4][6 8]]2.一维与二维相加结果:[[11 22 33][14 25 36]]3.三维与二维广播结果形状: (2, 3, 4)

Numpy广播机制(与PyTorch基本一致):

import numpy as np
import timeit# 最佳实践1: 优先使用广播替代显式循环
def sum_with_loop():a = np.arange(1000)b = np.arange(1000)result = np.zeros_like(a)for i in range(len(a)):result[i] = a[i] + b[i]return resultdef sum_with_broadcasting():a = np.arange(1000)b = np.arange(1000)return a + b  # 利用广播,无需显式循环# 性能对比
loop_time = timeit.timeit(sum_with_loop, number=1000)
broadcast_time = timeit.timeit(sum_with_broadcasting, number=1000)
print(f"循环耗时: {loop_time:.4f}秒")      # 约0.15秒
print(f"广播耗时: {broadcast_time:.4f}秒")  # 约0.002秒
print(f"广播比循环快 {loop_time/broadcast_time:.1f}倍")  # 约75倍# 最佳实践2: 使用np.newaxis显式扩展维度
a = np.array([1, 2, 3])  # 形状 (3,)
b = np.array([4, 5])     # 形状 (2,)# 错误写法:a + b 会触发维度不兼容错误# 正确写法:使用np.newaxis扩展维度
result = a[:, np.newaxis] + b  # a扩展为(3,1),b扩展为(1,2),结果为(3,2)
print("\n使用np.newaxis扩展维度:")
print(result)
# 输出:
# [[5 6]
#  [6 7]
#  [7 8]]# 最佳实践3: 内存高效的广播操作
# 错误写法:创建大中间数组
a = np.ones((1000, 1000))
b = np.ones((1000, 1000))
c = a * b  # 创建临时数组,占用额外内存
result = c.sum()# 正确写法:使用out参数避免临时数组
result = np.zeros((1000, 1000))
np.multiply(a, b, out=result)  # 直接将结果写入预分配的数组
final_result = result.sum()    

输出结果:

循环耗时: 0.3540秒
广播耗时: 0.0039秒
广播比循环快 90.5倍使用np.newaxis扩展维度:
[[5 6][6 7][7 8]]

卷积:

import numpy as npdef convolution_2d(input_image, kernel, stride=1, padding=0):"""实现二维卷积操作参数:input_image: 输入图像,形状为 (height, width)kernel: 卷积核,形状为 (kernel_height, kernel_width)stride: 步长padding: 填充大小返回:卷积结果,形状为 (output_height, output_width)"""# 获取输入图像和卷积核的形状img_h, img_w = input_image.shapek_h, k_w = kernel.shape# 计算输出图像的形状output_h = (img_h + 2 * padding - k_h) // stride + 1output_w = (img_w + 2 * padding - k_w) // stride + 1# 填充输入图像padded_image = np.pad(input_image, ((padding, padding), (padding, padding)), mode='constant')# 初始化输出图像output = np.zeros((output_h, output_w))# 执行卷积操作for i in range(output_h):for j in range(output_w):# 提取当前卷积区域region = padded_image[i*stride:i*stride+k_h, j*stride:j*stride+k_w]# 计算卷积值(对应元素相乘后求和)output[i, j] = np.sum(region * kernel)return output# 示例:应用边缘检测卷积核
# 输入图像
image = np.array([[10, 10, 10, 0, 0, 0],[10, 10, 10, 0, 0, 0],[10, 10, 10, 0, 0, 0],[0, 0, 0, 10, 10, 10],[0, 0, 0, 10, 10, 10],[0, 0, 0, 10, 10, 10]
], dtype=np.float32)# 水平边缘检测卷积核(Sobel算子)
kernel_h = np.array([[1, 2, 1],[0, 0, 0],[-1, -2, -1]
], dtype=np.float32)# 垂直边缘检测卷积核(Sobel算子)
kernel_v = np.array([[1, 0, -1],[2, 0, -2],[1, 0, -1]
], dtype=np.float32)# 应用卷积
edge_h = convolution_2d(image, kernel_h, stride=1, padding=1)
edge_v = convolution_2d(image, kernel_v, stride=1, padding=1)# 计算边缘强度(水平和垂直方向的平方和开方)
edge_strength = np.sqrt(edge_h**2 + edge_v**2)print("原始图像:")
print(image)
print("\n水平边缘:")
print(np.round(edge_h, 1))
print("\n垂直边缘:")
print(np.round(edge_v, 1))
print("\n边缘强度:")
print(np.round(edge_strength, 1))    

输出结果:

原始图像:
[[10. 10. 10.  0.  0.  0.][10. 10. 10.  0.  0.  0.][10. 10. 10.  0.  0.  0.][ 0.  0.  0. 10. 10. 10.][ 0.  0.  0. 10. 10. 10.][ 0.  0.  0. 10. 10. 10.]]水平边缘:
[[-30. -40. -30. -10.   0.   0.][  0.   0.   0.   0.   0.   0.][ 30.  40.  20. -20. -40. -30.][ 30.  40.  20. -20. -40. -30.][  0.   0.   0.   0.   0.   0.][  0.   0.  10.  30.  40.  30.]]垂直边缘:
[[-30.   0.  30.  30.   0.   0.][-40.   0.  40.  40.   0.   0.][-30.   0.  20.  20.   0.  10.][-10.   0. -20. -20.   0.  30.][  0.   0. -40. -40.   0.  40.][  0.   0. -30. -30.   0.  30.]]边缘强度:
[[42.4 40.  42.4 31.6  0.   0. ][40.   0.  40.  40.   0.   0. ][42.4 40.  28.3 28.3 40.  31.6][31.6 40.  28.3 28.3 40.  42.4][ 0.   0.  40.  40.   0.  40. ][ 0.   0.  31.6 42.4 40.  42.4]]

池化:

import numpy as npdef max_pooling_2d(input_image, pool_size=2, stride=2):"""实现二维最大池化操作参数:input_image: 输入图像,形状为 (height, width)pool_size: 池化窗口大小stride: 步长返回:池化结果,形状为 (output_height, output_width)"""# 获取输入图像的形状img_h, img_w = input_image.shape# 计算输出图像的形状output_h = (img_h - pool_size) // stride + 1output_w = (img_w - pool_size) // stride + 1# 初始化输出图像output = np.zeros((output_h, output_w))# 执行最大池化操作for i in range(output_h):for j in range(output_w):# 提取当前池化区域region = input_image[i*stride:i*stride+pool_size, j*stride:j*stride+pool_size]# 计算区域内的最大值output[i, j] = np.max(region)return outputdef average_pooling_2d(input_image, pool_size=2, stride=2):"""实现二维平均池化操作参数:input_image: 输入图像,形状为 (height, width)pool_size: 池化窗口大小stride: 步长返回:池化结果,形状为 (output_height, output_width)"""# 获取输入图像的形状img_h, img_w = input_image.shape# 计算输出图像的形状output_h = (img_h - pool_size) // stride + 1output_w = (img_w - pool_size) // stride + 1# 初始化输出图像output = np.zeros((output_h, output_w))# 执行平均池化操作for i in range(output_h):for j in range(output_w):# 提取当前池化区域region = input_image[i*stride:i*stride+pool_size, j*stride:j*stride+pool_size]# 计算区域内的平均值output[i, j] = np.mean(region)return output# 示例:应用池化操作
# 输入图像
image = np.array([[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]
], dtype=np.float32)# 应用最大池化
max_pooled = max_pooling_2d(image, pool_size=2, stride=2)# 应用平均池化
avg_pooled = average_pooling_2d(image, pool_size=2, stride=2)print("原始图像:")
print(image)
print("\n最大池化结果:")
print(max_pooled)
print("\n平均池化结果:")
print(avg_pooled)    

输出结果:

原始图像:
[[ 1.  2.  3.  4.][ 5.  6.  7.  8.][ 9. 10. 11. 12.][13. 14. 15. 16.]]最大池化结果:
[[ 6.  8.][14. 16.]]平均池化结果:
[[ 3.5  5.5][11.5 13.5]]

@浙大疏锦行

相关文章:

  • Python Web项目打包(Wheel)与服务器部署全流程
  • Pyppeteer企业级爬虫实战:从动态渲染到反反爬突破(2025终极指南)
  • 正常流程、可选流程和异常
  • 智能职业发展系统:AI驱动的职业规划平台技术解析
  • MySQL:CTE 通用表达式
  • 第二十八章 字符串与数字
  • 基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
  • 人生中第一次开源:java版本的supervisor,支持web上管理进程,查看日志
  • 风力发电机领域的声纹监测产品
  • Java编程之桥接模式
  • LLMs 系列科普文(4)
  • CSP-38th
  • MCP笔记:介绍和原理
  • 高保真组件库:按钮
  • Docker 优势与缺点全面解析:容器技术的利与弊
  • Spring整合Mybatis
  • springboot2.x升级springboot3.x
  • 10万QPS高并发请求,如何防止重复下单
  • 从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
  • SeaweedFS S3 Spring Boot Starter
  • 一级a做爰片免费网站短视频播放/如何建立一个网站平台
  • 网站降权怎么做/青岛关键词排名系统
  • dreamwear做网站/自助建站系统个人网站
  • 尤溪网站开发/关键词排名软件官网
  • 桥 网站建设/优化模型数学建模
  • 旅游网站开发工具/百度推广渠道户