学习一个random_shuffle()

本文介绍C++ STL中random_shuffle函数的使用方法,演示了如何利用该函数对vector容器及字符数组进行随机排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STL中的函数random_shuffle()用来对一个元素序列进行重新排序(随机的),函数原型如下:

template<class RandomAccessIterator>  
   void random_shuffle(  
      RandomAccessIterator _First, //指向序列首元素的迭代器  
      RandomAccessIterator _Last  //指向序列最后一个元素的下一个位置的迭代器  
   );  

例子:

#include "stdafx.h"  
#include <iostream>  
#include <vector>  
#include <algorithm>  
using namespace std;  

int _tmain(int argc, _TCHAR* argv[])  
{  
     vector<string> str;  
     str.push_back("hello");  
     str.push_back("world");  
     str.push_back("welcome");  
     str.push_back("to");  
     str.push_back("Beijing");  

     std::random_shuffle(str.begin(),str.end());//迭代器  

     for(int j = 0; j < str.size(); j++)  
     {  
         cout<<str[j].c_str()<<" ";  
     }  
     cout<<endl;  

    system("pause");  
    return 0;  
}  

random_shuffle还可以用于数组:
[


#include "stdafx.h"  
#include <iostream>  
#include <vector>  
#include <algorithm>  
using namespace std;  

int _tmain(int argc, _TCHAR* argv[])  
{  
    char arr[] = {'a', 'b', 'c', 'd', 'e', 'f'};  

     std::random_shuffle(arr,arr+6);//迭代器  

     for(int j = 0; j < 6; j++)  
     {  
         cout<<arr[j]<<" ";  
     }  
     cout<<endl;  

    system("pause");  
    return 0;  
}  
<think>我们有一个列表`self.img_paths`,我们想要随机打乱这个列表的顺序。 在Python中,可以使用`random`模块的`shuffle`函数来实现。 注意:`random.shuffle`是原地操作,也就是说它会直接修改原列表,而不是返回一个新的打乱顺序的列表。 代码示例: ```python import random # 假设我们有一个包含图像路径的列表 self.img_paths = ['img1.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg', 'img5.jpg'] # 使用random.shuffle打乱列表 random.shuffle(self.img_paths) # 现在self.img_paths的顺序已经被随机打乱 print(self.img_paths) # 输出可能是:['img3.jpg', 'img1.jpg', 'img5.jpg', 'img2.jpg', 'img4.jpg'] ``` 解释: - `random.shuffle(x[, random])`:将序列x随机打乱位置。可选参数`random`是一个无参数函数,返回[0.0, 1.0)之间的随机浮点数,默认使用`random.random()`。 - 这个函数没有返回值,而是直接对传入的列表进行修改(原地操作)。 使用场景: 在机器学习中,我们通常需要在训练前将数据集打乱,以避免数据集中可能存在的一些顺序模式(如按类别排序)影响训练效果。 注意: 如果希望保持原列表不变,而创建一个新的被打乱顺序的列表,可以这样做: ```python import random shuffled_list = random.sample(self.img_paths, len(self.img_paths)) ``` 这里`random.sample(population, k)`返回一个长度为k的新列表,其中包含从population中随机选取的元素。当k等于原列表长度时,就相当于打乱顺序。 另外,如果使用`numpy`,也可以使用`numpy.random.shuffle`,它也是原地操作: ```python import numpy as np np.random.shuffle(self.img_paths) ``` 但是,需要注意的是,`random.shuffle`和`numpy.random.shuffle`都是原地操作,而`random.sample`会返回一个新的列表。 相关问题: 1. 如何在不修改原列表的情况下获得一个打乱顺序的新列表? 2. `random.shuffle`和`numpy.random.shuffle`有什么区别? 3. 如何设置随机种子以确保每次打乱的顺序相同(可复现)? 4. 在深度学习中,为什么通常需要在每个训练周期(epoch)之前打乱数据?</think># 使用 `random.shuffle()` 打乱图像路径列表 `random.shuffle(self.img_paths)` 这段代码用于**随机打乱存储在 `self.img_paths` 列表中的图像路径顺序**。这是机器学习/深度学习数据准备中非常关键的一步,尤其是在训练模型时。 ## 完整实现和解释 ```python import random import os from imutils import paths class ImageDataset: def __init__(self, data_dirs): """ 初始化图像数据集 参数: data_dirs: 包含图像目录的列表 """ self.img_paths = [] # 存储所有图像路径 # 收集所有目录中的图像路径 for data_dir in data_dirs: # 确保目录存在 if not os.path.exists(data_dir): print(f"警告: 目录不存在 - {data_dir}") continue # 添加目录中的所有图像路径 self.img_paths.extend(paths.list_images(data_dir)) # 打印初始统计信息 print(f"加载了 {len(self.img_paths)} 张图像") # 打乱图像路径顺序 self.shuffle_images() def shuffle_images(self): """随机打乱图像路径顺序""" print("正在打乱图像顺序...") random.shuffle(self.img_paths) print("图像顺序已随机打乱") def get_batch(self, batch_size=32, start_idx=0): """获取指定大小的批次图像路径""" end_idx = min(start_idx + batch_size, len(self.img_paths)) return self.img_paths[start_idx:end_idx] # 使用示例 if __name__ == "__main__": # 定义数据目录 data_directories = [ "dataset/train", "dataset/validation" ] # 创建数据集实例 dataset = ImageDataset(data_directories) # 获取前5个图像路径(已打乱顺序) print("\n随机图像路径示例:") for i, path in enumerate(dataset.get_batch(5)): print(f"{i+1}. {path}") ``` ## `random.shuffle()` 的详细解释 1. **功能**: - 原地(in-place)随机重排序列元素的顺序 - 修改原始列表,不返回新列表 - 使用 Fisher-Yates 洗牌算法,确保每个排列出现的概率相等 2. **算法原理**: ```python # Fisher-Yates 洗牌算法的Python实现 def fisher_yates_shuffle(arr): n = len(arr) for i in range(n-1, 0, -1): # 随机选择0到i之间的索引 j = random.randint(0, i) # 交换元素 arr[i], arr[j] = arr[j], arr[i] ``` 3. **为什么需要打乱数据顺序**: - **避免模型学习到数据顺序**:如果数据按类别排序,模型可能会学习这种顺序而非实际特征 - **提高泛化能力**:确保每个批次包含多样化的样本 - **防止训练偏差**:确保训练过程中所有类别均匀出现 - **优化梯度下降**:随机顺序提供更平滑的梯度更新 ## 实际应用场景 1. **训练深度学习模型**: ```python # 在训练循环中 for epoch in range(num_epochs): # 每个epoch开始时打乱数据 random.shuffle(train_dataset.img_paths) for batch_idx in range(0, len(train_dataset), batch_size): batch_paths = train_dataset.img_paths[batch_idx:batch_idx+batch_size] # 加载并处理图像... # 训练模型... ``` 2. **创建随机样本展示**: ```python def show_random_samples(dataset, num_samples=9): """显示随机样本图像""" # 确保数据已打乱 if not hasattr(dataset, 'shuffled') or not dataset.shuffled: random.shuffle(dataset.img_paths) fig, axes = plt.subplots(3, 3, figsize=(10, 10)) for i, ax in enumerate(axes.flat): img_path = dataset.img_paths[i] img = plt.imread(img_path) ax.imshow(img) ax.set_title(os.path.basename(img_path)) ax.axis('off') plt.show() ``` ## 高级用法和注意事项 1. **固定随机种子确保可复现性**: ```python def set_seed(seed=42): """设置随机种子以确保结果可复现""" random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) # 在训练前调用 set_seed(42) random.shuffle(dataset.img_paths) # 每次运行结果相同 ``` 2. **分层抽样打乱**: ```python from sklearn.model_selection import train_test_split def stratified_shuffle(dataset, labels): """保持类别分布的随机打乱""" # 先划分训练/测试集 train_idx, test_idx = train_test_split( range(len(dataset)), test_size=0.2, stratify=labels, random_state=42 ) # 分别打乱 random.shuffle(train_idx) random.shuffle(test_idx) return train_idx, test_idx ``` 3. **大型数据集的分块打乱**: ```python def chunk_shuffle(arr, chunk_size=10000): """分块打乱大型数据集""" # 将列表分成多个块 chunks = [arr[i:i+chunk_size] for i in range(0, len(arr), chunk_size)] # 打乱块顺序 random.shuffle(chunks) # 打乱每个块内部顺序 for chunk in chunks: random.shuffle(chunk) # 合并所有块 return [item for chunk in chunks for item in chunk] # 用于超大型数据集 dataset.img_paths = chunk_shuffle(dataset.img_paths, chunk_size=5000) ``` ## 性能考虑 1. **时间复杂度**: - `random.shuffle()` 的时间复杂度是 O(n),其中 n 是列表长度 - 对于大型数据集(>100万样本),考虑使用内存映射文件或分块处理 2. **替代方案**: ```python # 使用numpy(更快) import numpy as np shuffled_indices = np.random.permutation(len(dataset.img_paths)) dataset.img_paths = [dataset.img_paths[i] for i in shuffled_indices] # 使用PyTorch DataLoader的shuffle参数 from torch.utils.data import DataLoader dataloader = DataLoader( dataset, batch_size=32, shuffle=True, # 自动打乱 num_workers=4 ) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值