当使用ChatGPT帮我们工作的时候,确实很大一部分人就会失业,当然也有很大一部分人收益其中。我今天继续使用其帮我了解新的内容,也就是timm库。毫不夸张的说,Chat GPT比百分之80的博客讲的更清楚更好,仅次于源码。
当提到计算机视觉的深度学习框架时,PyTorch无疑是最受欢迎的选择之一。PyTorch拥有强大的自动求导功能、易于使用的API和广泛的社区支持。而针对计算机视觉任务,timm库则是一个值得推荐的PyTorch扩展库。timm(Timm is a model repository for PyTorch)库提供了预训练模型、模型构建块和模型训练的实用工具。timm库可以帮助开发者快速构建和训练深度学习模型,同时支持多种图像分类、分割和检测任务,特别是结合torch和torchvision的使用,对你训练模型,事半功倍。
本文将介绍timm库的基本用法,并使用timm库训练一个图像分类模型作为示例。本文将假设读者已经对PyTorch和计算机视觉的基本概念有一定的了解,下面详细说一下。
首先简单梳理一下timm的用途:
图像分类(Image Classification):Timm库包含了许多用于图像分类的预训练模型,如ResNet、VGG、EfficientNet等。你可以使用这些模型进行图像分类任务,如图像分类、图像回归等。
使用EfficientNet模型进行图像分类:
model = timm.create_model('efficientnet_b0', pretrained=True)
使用ResNet模型进行图像分类:
model = timm.create_model('resnet50', pretrained=True)
目标检测(Object Detection):Timm库提供了一系列在目标检测和物体识别任务上表现优秀的模型,如EfficientDet、YOLO、RetinaNet等。你可以使用这些模型进行目标检测和物体识别任务。
使用EfficientDet模型进行目标检测:
model = timm.create_model('efficientdet_d0', pretrained=True)
使用YOLOv5模型进行目标检测:
model = timm.create_model('yolov5s', pretrained=True)
图像分割(Image Segmentation):Timm库支持各种图像分割模型,如DeepLab、U-Net、PSPNet等。你可以使用这些模型进行图像分割任务,例如语义分割、实例分割等。
使用DeepLabV3模型进行语义分割:
model = timm.create_model('deeplabv3_resnet50', pretrained=True)
使用PSPNet模型进行图像分割:
model = timm.create_model('pspnet_resnet50', pretrained=True)
模型微调和迁移学习:Timm库提供了方便的函数和工具,使你能够轻松地微调和迁移学习预训练模型。你可以使用Timm库中的模型作为基础模型,并在自己的数据集上进行微调。
model = timm.create_model('resnet50', pretrained=True) # 在新数据集上进行微调 # ...
模型评估和验证:Timm库提供了各种评估指标和工具,用于模型的性能评估和验证。你可以使用这些工具来评估模型在不同任务上的性能,并进行模型选择和比较。
总之,Timm库是一个功能齐全的模型库,涵盖了图像分类、目标检测、图像分割等多个计算机视觉任务,并提供了方便的接口和实用工具,简化了模型开发和实验过程。你可以根据具体的需求使用Timm库中的不同模型和功能来完成相应的任务。
下面来简单学习一下。
timm库可以通过pip命令进行安装:
pip install timm
安装完成后,我们在Python脚本或者Jupyter Notebook中导入timm库。
import timm
timm库提供了多个预训练模型,这些模型可以在ImageNet等数据集上进行预训练,也可以在其他数据集上进行微调。
加载预训练模型的代码非常简单,下面我们加载需要的预训练模型权重:
import timm m = timm.create_model('vgg16', pretrained=True) m.eval()
上面代码就会创建一个VGG-16的预训练模型,我们可以通过修改模型名称来加载其他预训练模型,例如:
model = timm.create_model('efficientnet_b0', pretrained=True)
上面代码就会创建一个EfficientNet-B0的预训练模型。
加载所有的预训练模型列表(pprint是美化打印的标准库):
import timm from pprint import pprint model_names = timm.list_models(pretrained=True) pprint(model_names) >>> ['adv_inception_v3', 'cspdarknet53', 'cspresnext50', 'densenet121', 'densenet161', 'densenet169', 'densenet201', 'densenetblur121d', 'dla34', 'dla46_c', ... ]
利用通配符加载所有的预训练模型列表:
import timm from pprint import pprint model_names = timm.list_models('*resne*t*') pprint(model_names) >>> ['cspresnet50', 'cspresnet50d', 'cspresnet50w', 'cspresnext50', ... ]
如果需要自定义模型,我们可以使用timm库提供的模型构建块。模型构建块是模型的组成部分,可以灵活的组合和定制。例如我们可以使用timm库提供的ConvBnAct模块来定义一个卷积-BatchNorm-ReLU的模型构建块:
import torch.nn as nn from timm.models.layers import ConvBnAct block = ConvBnAct(in_channels=3, out_channels=64, kernel_size=3, stride=1, act_layer=nn.ReLU) print(block)
这个代码会创建一个输入通道为3、输出通道为64、卷积核大小为3、步长为1、激活函数为ReLU的卷积-BatchNorm-ReLU模块。
我们打印一下,可以清晰的看到结果:
ConvNormAct( (conv): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn): BatchNormAct2d( 64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True (drop): Identity() (act): ReLU(inplace=True) ) )
再来一个示例:
import timm class CustomModel(timm.models.VisionTransformer): def __init__(self, **kwargs): super().__init__(**kwargs) self.head = torch.nn.Linear(self.head.in_features, num_classes) model = CustomModel(img_size=224, patch_size=16, embed_dim=768, depth=12, num_heads=12, num_classes=100)
在上面的代码中,我们创建了一个继承自timm库中VisionTransformer的自定义模型,并修改了模型的输出层以适应我们的任务。
下面我们将介绍如何使用timm库训练和测试图像分类模型。timm库是一个用于计算机视觉任务的PyTorch库,它提供了许多预训练模型和常用的计算机视觉工具。我们将使用CIFAR-10数据集作为示例。
import torch import torchvision import torchvision.transforms as transforms # 数据预处理 transform = transforms.Compose([ transforms.RandomHorizontalFlip(), transforms.RandomCrop(32, padding=4), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) # 加载CIFAR-10数据集 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=100, shuffle=True, num_workers=2) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)
import timm model = timm.create_model('resnet50', pretrained=True, num_classes=10)
import torch.optim as optim criterion = torch.nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练模型 num_epochs = 10 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model.to(device) for epoch in range(num_epochs): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() print(f"Epoch {epoch + 1}, Loss: {running_loss / (i + 1)}")
correct = 0 total = 0 model.eval() with torch.no_grad(): for data in testloader: images, labels = data images, labels = images.to(device), labels.to(device) outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print(f"Accuracy on test set: {100 * correct / total}%")
下面是一个简单的图像分类示例,使用timm库中的ResNet50模型:
import torch import timm from PIL import Image import torchvision.transforms as transforms # 加载ResNet50模型 model = timm.create_model('vgg16', pretrained=True) # 将模型设置为评估模式 model.eval() # 加载图像并进行预处理 image = Image.open(r"D:\Desktop\workdata\data\segmentation_dataset\images\Abyssinian_24.jpg") # 定义图像预处理转换 preprocess = transforms.Compose([ transforms.Resize((256, 256)), # 调整图像大小为256x256 transforms.ToTensor(), # 转换为Tensor类型 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), # 归一化 ]) # 应用预处理转换 processed_image = preprocess(image) # 查看处理后的图像形状和数值范围 print("Processed image shape:", processed_image.shape) print("Processed image range:", processed_image.min(), "-", processed_image.max()) # 5. 可选:将处理后的图像转换回PIL图像对象 processed_pil_image = transforms.ToPILImage()(processed_image) # 6. 可选:显示处理后的图像 processed_pil_image.show() # 将输入张量转换为批处理张量 input_batch = processed_image.unsqueeze(0) # 将输入张量传递给模型并获取输出 with torch.no_grad(): output = model(input_batch) # 获取预测结果 _, predicted = torch.max(output.data, 1) # 打印预测结果 print(predicted.item())
在上面的代码中,我们首先加载了ResNet50模型,并将其设置为评估模式。然后,我们加载了一个图像,并使用timm库中的预处理函数对其进行预处理。接下来,我们将输入张量转换为批处理张量,并将其传递给模型以获取输出。最后,我们使用torch.max函数获取预测结果,并将其打印出来。
timm中所有模型都可以从模型中获取各种类型的特征,用于除分类之外的任务。
Penultimate Layer Features的中文含义是 "倒数第2层的特征",即 classifier 之前的特征。timm 库可以通过多种方式获得倒数第二个模型层的特征,而无需进行模型的手术。
import torch import timm m = timm.create_model('resnet50', pretrained=True, num_classes=1000) o = m(torch.randn(2, 3, 224, 224)) print(f'Pooled shape: {o.shape}') # Pooled shape: torch.Size([2, 2048])
获取分类器之后的特征:
import torch import timm m = timm.create_model('ese_vovnet19b_dw', pretrained=True) o = m(torch.randn(2, 3, 224, 224)) print(f'Original shape: {o.shape}') m.reset_classifier(0) o = m(torch.randn(2, 3, 224, 224)) print(f'Pooled shape: {o.shape}') # Pooled shape: torch.Size([2, 1024])
输出多尺度特征:默认情况下,大多数模型将输出5个stride(并非所有模型都有那么多),第一个从 stride=2开始(有些从1,4开始)。
import torch import timm m = timm.create_model('resnest26d', features_only=True, pretrained=True) o = m(torch.randn(2, 3, 224, 224)) for x in o: print(x.shape) # output torch.Size([2, 64, 112, 112]) torch.Size([2, 256, 56, 56]) torch.Size([2, 512, 28, 28]) torch.Size([2, 1024, 14, 14]) torch.Size([2, 2048, 7, 7])
当你在使用timm库进行特征提取时,可以选择使用create_model
函数的features_only
参数来直接返回模型的特征提取部分,而不包括分类器部分。这可以帮助简化代码,避免手动移除最后一层分类器。
也可以手动去除,代码如下:
import torch import timm # 1. 加载预训练模型 model = timm.create_model('resnet50', pretrained=True) # 2. 移除最后一层分类器 model = torch.nn.Sequential(*list(model.children())[:-1]) # 3. 设置模型为评估模式 model.eval() # 4. 加载图像 input = torch.randn(1, 3, 224, 224) # 假设输入为224x224的RGB图像 # 5. 特征提取 features = model(input) # 6. 打印提取到的特征 print("Features shape:", features.shape)
在上述示例中,我们使用timm库加载了一个预训练的ResNet-50模型,并通过移除最后一层分类器来获得特征提取模型。然后,我们将模型设置为评估模式(model.eval()
)以确保不进行训练。接下来,我们加载输入图像,并将其传递给模型以获取特征表示。最后,我们打印出提取到的特征的形状。
模型融合是一种提高模型性能的有效方法。当涉及到更复杂的模型融合时,以下是一些深层次的技巧和注意事项:
模型选择和组合:选择具有不同架构和特性的模型进行融合,例如卷积神经网络(CNN)、循环神经网络(RNN)和注意力机制(Attention)。确保选择的模型能够相互补充,以提高整体性能。
特征融合:除了融合模型输出,还可以考虑融合模型的中间层特征。通过提取和融合模型的不同层级特征,可以获得更丰富和多样化的信息。
加权融合:为每个模型分配适当的权重,以平衡其贡献。权重可以基于预训练模型的性能、验证集表现等进行选择,也可以通过训练得到。
模型蒸馏:使用一个更大、更复杂的模型(教师模型)来指导训练一个较小、更轻量级的模型(学生模型)。学生模型可以通过蒸馏教师模型的知识,从而提高模型的泛化能力。
集成学习:除了简单的模型融合,可以尝试集成学习方法,如投票、堆叠(stacking)、混合(blending)等。这些方法通过结合多个模型的预测结果,提高模型的鲁棒性和准确性。
数据增强:对训练数据进行多样化的增强操作,如随机裁剪、旋转、翻转等,以增加数据的多样性和模型的鲁棒性。确保在融合模型中使用相同的数据增强方式,以保持一致性。
模型选择和调优:通过交叉验证等方法,选择最佳的模型组合并进行超参数调优。可以使用网格搜索、随机搜索等技术来搜索最佳超参数组合。
总之,模型融合是一个灵活且有挑战性的任务,需要结合具体问题和数据集来进行调整和优化。不同的技巧和策略适用于不同的场景,因此需要不断实验和调整以找到最佳的模型融合方法。
以下是一个使用timm库进行模型融合的示例:
import torch import timm class ModelEnsemble(torch.nn.Module): def __init__(self, models): super().__init__() self.models = torch.nn.ModuleList(models) def forward(self, x): outputs = [model(x) for model in self.models] return torch.mean(torch.stack(outputs), dim=0) # 加载多个预训练模型 model1 = timm.create_model('resnet18', pretrained=True, num_classes=100) model2 = timm.create_model('vgg16', pretrained=True, num_classes=100) # 创建模型融合 ensemble = ModelEnsemble([model1, model2]) # 使用融合模型进行预测 output = ensemble(input_tensor)
在上面的代码中,我们首先加载了两个预训练模型。然后,我们创建了一个模型融合类,该类将多个模型的输出进行平均。最后,我们使用融合模型进行预测。
我们打印一下模型结构,我省略一些代码,只show关键点:
ModelEnsemble( (models): ModuleList( (0): ResNet( (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (act1): ReLU(inplace=True) (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False) (layer1): Sequential( ........ (这里省略了ResNet的网络结构) ) (global_pool): SelectAdaptivePool2d (pool_type=avg, flatten=Flatten(start_dim=1, end_dim=-1)) (fc): Linear(in_features=512, out_features=100, bias=True) ) (1): VGG( (features): Sequential( (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): ReLU(inplace=True) (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (3): ReLU(inplace=True) (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) .......(这里省略了VGG16的模型结构) ) (pre_logits): ConvMlp( (fc1): Conv2d(512, 4096, kernel_size=(7, 7), stride=(1, 1)) (act1): ReLU(inplace=True) (drop): Dropout(p=0.0, inplace=False) (fc2): Conv2d(4096, 4096, kernel_size=(1, 1), stride=(1, 1)) (act2): ReLU(inplace=True) ) (head): ClassifierHead( (global_pool): SelectAdaptivePool2d (pool_type=avg, flatten=Flatten(start_dim=1, end_dim=-1)) (fc): Linear(in_features=4096, out_features=100, bias=True) (flatten): Identity() ) ) ) )
在上面模型融合过程中,首先将输入图像传递给第一个模型,获取其输出特征。然后,将这些特征作为输入传递给第二个模型,以获得最终的分类结果。通过对两个模型的输出进行融合,可以综合利用它们的优势,提高整体性能或泛化能力。
需要注意的是,这只是一个简单的示例,实际的模型融合可能涉及更复杂的策略和技巧。具体的模型融合方法取决于任务的需求和数据集的特点。可以根据实际情况进行调整和改进,以获得更好的结果 。
当涉及更复杂的模型融合时,常见的技术包括集成学习方法,如堆叠集成和投票集成。下面是一个更复杂的模型融合示例,使用堆叠集成的方法:
import torch import timm # 1. 加载并初始化要融合的模型 model1 = timm.create_model('resnet50', pretrained=True) model2 = timm.create_model('efficientnet_b0', pretrained=True) model3 = timm.create_model('densenet121', pretrained=True) # 2. 定义融合模型 class FusionModel(torch.nn.Module): def __init__(self, model1, model2, model3): super(FusionModel, self).__init__() self.model1 = model1 self.model2 = model2 self.model3 = model3 self.fc = torch.nn.Linear(3, 1) # 假设最终输出为单个值 def forward(self, x): output1 = self.model1(x) output2 = self.model2(x) output3 = self.model3(x) fused_output = torch.cat([output1, output2, output3], dim=1) fused_output = self.fc(fused_output) return fused_output # 3. 创建融合模型实例 fusion_model = FusionModel(model1, model2, model3) # 4. 使用融合模型进行推理 input = torch.randn(1, 3, 224, 224) # 假设输入为224x224的RGB图像 output = fusion_model(input) # 5. 打印输出结果 print("Fused output shape:", output.shape)
在上述示例中,我们加载了三个预训练模型,并使用堆叠集成的方法将它们的输出连接在一起。连接后的输出经过一个全连接层进行进一步处理,最终得到融合模型的输出。
不经一番彻骨寒 怎得梅花扑鼻香
假设我们想查看安装了ABAP应用服务器的Linux系统某个文件目录下的明细,如果直接登录LinuxShell,使用ls-l命令即可。比如:ls-l//bas/CGC5/src/krn/abap/runt其实我们可以使用ABAP提供的CALL关键字,直接在ABAP应用层,发起对操作系统shell命令行的调用。后者的执行结果,返回给ABAP层,这样ABAP应用开发人员就能在此基础上进行一些处理,开发一些工具。我写了一个简单的ABAP报表来包装这个CALL关键字的调用:REPORTzlinux. PARAMETERS:commandTYPEstringLOWERCASEDEFAULT'ls-l//bas/CGC5/src/krn/abap/runt'. DATA:commtext(120), itab(255)OCCURS10WITHHEADERLINE, lv_folderTYPEstring. START-OF-SELECTION. PERFORMinit. CALL'SYSTEM'ID'COMMAND'FIELDcommt
?点击“博文视点Broadview”,获取更多书讯01Turtle那些事儿Turtle(也被称为海龟绘图)是一个绘图库,它的绘图原理是模拟一只小海龟在屏幕上爬行,其爬行路径就形成了绘制的图形。因此使用Turtle绘图既简单又有趣,非常适用于Python入门学习,也适用于Python进阶学习。▊Turtle中的基本概念在Turtle中有两个重要的基本概念。1屏幕:是Turtle的绘图区域,我们可以设置屏幕的大小和背景颜色,如下图所示。注意,屏幕的坐标原点在屏幕的中心。2海龟(别名:画笔):绘图所用的画笔,它是一个Turtle类所创建的对象。海龟有颜色、画线的宽度、位置和方向等属性,如下图所示。▊使用Turtle绘制一个矩形示例代码如下:▊改变画笔▊设置画笔示例代码如下:▊填充颜色02绘制基本图形使用Turtle可以绘制直线、弧线和文本。当然,可以绘制直线就可以绘制各种多边形。▊绘制五角星示例代码如下:▊绘制圆形和弧线既然使用Turtle可以绘制弧线,那么也可以绘制圆形。我们通过一个示例实践一下绘制圆形和弧线,如下图所示。示例代码如下:本文节选自《看漫画学Python2:有趣、有料、好玩、
大家好,又见面了,我是全栈君。做一个积极的人 编码、改bug、提升自己我有一个乐园,面向编程,春暖花开!你好,JedisPoolConfigJava中使用Jedis作为连接Redis的工具。在使用Jedis的也可以配置JedisPool连接池,JedisPool配置参数大部分是由JedisPoolConfig的对应项来赋值的。本文简单总结几个常用的配置,然后通过源码(版本jedis-3.1.0)的角度让你理解配置这些参数的原理。首先了解一下池化((对象池、数据库连接池、线程池等等))的一些思想和好处。方便后面对JedisPoolConfig的配置的理解。池化的基本思想:1、可以在初始化的时候创建一些对象,当有需要使用的时候不直接从池中获取,提高响应速度;2、使用过的对象不进行销毁,保存起来,等下一次需要对象的时候,拿出来重复使用,减少频繁创建对象所造成的开销;3、创建的对象统一保存,方面管理和维护。池化好处总结:1、提高响应的速度2、降低资源的消耗3、方便管理和维护JedisPoolConfig配置说明类图和源码解析首先看一下类图:•BaseGenericObjectPool:封装公共
Proofs,Arguments,andZero-Knowledge01Proofs,Arguments,andZero-Knowledge02Chapter3DefinitionsandTechnicalPreliminaries3.1InteractiveProofs(交互式证明)3.2ArgumentSystems(论证系统)3.3RobustnessofDefinitionsandthePowerofInteraction3.4Schwartz-ZippelLemma3.5LowDegreeandMultilinearExtensions3.6Exercises3.1InteractiveProofs(交互式证明)给定函数f将{0,1}^n映射到有限范围R,f的k-消息交互式证明系统(IP)有在多项式时间poly(n)中运行的概率验证算法V和诚实确定性证明者算法P。V和P都有共同的输入x∈{0,1}^n,并且在协议开始时P提供了一个声称等于f(x)的值y。然后P和V交换一系列消息m1,m2,...,mk。P和V是“下一条消息计算算法”,当轮到V(P)发送消息mi时,V(P)输入
匹配中文字符的正则表达式:[u4e00-u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了匹配双字节字符(包括汉字在内):[^x00-xff] 评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)匹配空白行的正则表达式:ns*r 评注:可以用来删除空白行匹配HTML标记的正则表达式:<(S*?)[^>]*>.*?|<.*?/> 评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力匹配首尾空白字符的正则表达式:^s*|s*$ 评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式匹配Email地址的正则表达式:w+([-+.]w+)@w+([-.]w+).w+([-.]w+)* 评注:表单验证时很实用 匹配网址URL的正则表达式:[a-zA-z]+://[^s]* 评注:网上流传的版本功能很有限,上面这个基本可以满足需求 匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 评注:表
自我探索历程输出内容的一个好处是可以倒逼自己学习新内容,在上周连续输出了一些关于WPSJS的概要性知识同时,笔者也在自我充电中,增加一些网页开发的知识。首先说明下,当前笔者的现状:javascript语言入门水平,没有系统学习过前端工程师嘴里常说的三大网页开发框架(Vue、React、Angular)。在自我的学习过程中,笔者也是不断地去尝试和自我分辨哪些知识应该值得去学习,不同人站在不同角度分享出来的东西完全不同。而网页开发知识真的太深太广,选择比努力更重要。在笔者开发EasyShu图表插件过程中,仅需要了解图表库的知识,整个网页只需一个节点来绘制图表内容,所以前面说到的三大框架,肯定对此类需求无用武之地。对于OFFICE网页插件的开发,笔者也一直在思考,究竟哪些值得学习,一些前端开发口中说怎么过时不值得学习,有更好的替代的东西(如jquery过时论),或者提到我们更高效率地开发应该是基于框架来开发,这些结论是否适合当下的自己。诚然,OFFICE开发我们有天然的优势,是基于OFFICE软件有UI呈现的基础上开发,我们不必像一些专业网页开发工程师那样,过多地关注网页页面的布局、渲染等事
作者:掘金-隐冬https://juejin.cn/post/6915287057795874824WebRTC是谷歌于2011年开源的一个音视频处理引擎,可以实时的进行视频数据的采集,也就是说可以做直播,也可以做桌面录屏,桌面分享。使用起来还是比较简单的。这里我们来开发一个屏幕录制工具。首先我们在页面中创建一个video标签,用于展示录屏的内容,再创建四个按钮,一个屏幕分享,一个开始录制,一个停止录制,一个下载视频。<buttonid="start">屏幕分享</button> <buttonid="record">开始录制</button> <buttonid="stop">结束录制</button> <buttonid="download">下载视频</button> <videoautoplayplaysinlineid="player"></video> 复
我们了解HDFS的HA和Federation是从Hadoop1.0和Hadoop2.0的区别开始的。那么HA是代表什么?HA即为HighAvailability(高可用),用于解决NameNode单点故障的问题。该特性通过以热备的方式为NameNode提供一个备用者,一旦主NameNode出现故障,可以很快切换到备用的NameNode,从而实现对外提供服务。Federation即为联邦,该特性允许一个HDFS集群中存在多个NameNode,这些NameNode分管一部分目录(水平切分),彼此之间相互隔离,但共享底层的DataNode存储资源。之前的单点故障问题hadoop2.xNameNode是HDFS集群的单点故障点,每一个集群只有一个NameNode,如果这个机器或进程不可用,整个集群就无法使用,直到重启NameNode或者新启动一个NameNode节点。影响HDFS集群不可用主要包括以下两种情况:1)第一种情况是如机器宕机这样的意外情况,将导致集群不可用,只有在重启NameNode之后才可使用。2)第二种情况是计划内的软件或硬件升级(NameNode节点),将导致集群在短时间范围
根据CheckPoint披露的2020年5月全球威胁指数,Ursnif银行木马通过几批垃圾邮件投递行动使其排名跃升了19位。现在,Ursnif银行木马已经位列恶意软件排行榜第五名,有效的将其恶意影响范围增加了一倍。简要介绍Ursnif(又名Gozi、IFSB和Dreambot)是一种高风险的木马,一旦成功进入主机就会记录用户信息,包括击键记录、保存的用户名和密码、Web浏览行为、系统信息等等。该木马主要通过Word和Excel恶意附件进行传播,Ursnif最近攻击的新浪潮使其恶意软件指数快速跃升,这也与其变种之一Dreambot销声匿迹的报道不谋而合。Dreambot于2014年被发现,基于Ursnif泄露的源码二次开发。自从今年3月份以来,Dreambot的C&C服务器没有再进行相关操作。流行威胁此外,臭名昭著的银行木马Dridex在2020年3月首次进入榜单前十,并且在5月份继续广泛传播,连续两个月位列第一。最引人注目的是,移动恶意软件排名在5月也发生了变化,Android恶意软件主要通过欺诈性广告点击带来收入。CheckPoint威胁情报与研究总监MayaHorowitz
1.伪装自己有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作1.1设置请求头其中`User-Agent`代表用的哪个请求的浏览器代码如下:fromurllib.requestimporturlopen fromurllib.requestimportRequest url='http://www.server.com/login' user_agent='Mozilla/4.0(compatible;MSIE5.5;WindowsNT)' headers={'User-Agent':user_agent} request=Request(url,headers=headers) response=urlopen(request) page=response.read()复制对付防盗链,服务器会识别headers中的referer是不是它自己,如果不是,有的服务器不会响应,所以我们还可以在headers中加入referer代码如下:headers={
json包实现了json对象的编解码获取v变量的json编码将json编码的数据存入到解析v变量中如何实现延时解析实现标准HTML转义实现json字符串格式缩进和前缀剔除编码后数据中的空白字符结构体json编码选项应用获取v变量的json编码funcMarshal(vinterface{})([]byte,error)packagemain import( "encoding/json" "fmt" "log" ) typeUserstruct{ Namestring Ageint64 } funcmain(){ user:=User{"酷走天涯",27} b,error:=json.Marshal(user) iferror!=nil{ log.Fatal(error) } fmt.Println(string(b)) }复制image.png将json编码的数据存入到解析v变量中funcUnmarshal(data[]byte,vinterface{})errorpackagemain impo
在项目中,我们可能遇到有定时任务的需求。其一:定时执行任务。例如每天早上8点定时推送早报。其二:每隔一个时间段就执行任务。比如:每隔一个小时提醒自己起来走动走动,避免长时间坐着。今天,我跟大家分享下Python定时任务的实现方法。 1、第一种办法是最简单又最暴力。那就是在一个死循环中,使用线程睡眠函数sleep()。fromdatetimeimportdatetime importtime ''' 每个10秒打印当前时间。 ''' deftimedTask(): whileTrue: print(datetime.now().strftime("%Y-%m-%d%H:%M:%S")) time.sleep(10) if__name__=='__main__': timedTask()复制这种方法能够执行固定间隔时间的任务。如果timedTask()函数之后还有些操作,我们还使用死循环+阻塞线程。这会使得timedTask()一直占有CPU资源,导致后续操作无法执行。我建议谨重使用。2
作者:HughFDJackson 原标题:《DoesCurryHelp?》 原文地址:https://hughfdjackson.com/javascript/does-curry-help/ 译者:the5fire 注:这一篇应该跟上一篇一起读[译]为什么柯里化是有用的柯里化有用吗?在两年半前我写了这篇文章《为什么柯里化是有用的》——一些关于在JavaScript中使用柯里化函数的赞美之言。这篇文章轻松成为阅读量最大的一篇,每个月给我带来许多读者。但是随着时间流逝,时间发生了变化,我也是。依靠这个技巧让代码变得更有表达力仍旧是一个好的想法吗?我并不是那么确信。“这不是Haskell”当我一开始提出要把柯里化作为一个新增功能放到我们工作中的工具箱中时,我的同事William(不是真名)坚决坚持:这不是Haskell!我同样固执地争论道我们需要吸取好的技巧无论是在什么地方发现的,不论源码有多么晦涩。(后来)我花了一段时间才意识到他是多么正确。简单或许很重要,但是易用仍然重要用他的话来说就是——“简单致使易用”,RichHickey(the5fire注:Clojure作者)鼓励把简单和易用
【热门下载】2015中国数据分析师行业峰会精彩PPT下载(共计21个文件)关注PPV课微信菜单栏回复“2015数据分析师”即可下载来源:CSDN 作者:geekmajia 本人住在有人间天堂之称的城市,6年多开发经验,最近2年主要在做大数据相关的开发,最近考虑换工作,基本也只考虑大数据相关岗位。目前新工作已经找好,但想分享最近面试的失败经历(成功的那些就不讲了),吐槽吐槽,跟广大吃瓜群众分享一下过程中的经历心得,我的语文体育老师教的,还请大家莫怪。 1国内知名电信运营商,其下面的大数据研究院,面两轮一面:技术人员面,先自我介绍,项目经验相关介绍,问比较细,问了一些Hadoop、HBase的问题,JAVA基础,JVM内存分配小于32G原因,G1和CMS对比,问关系型数据库事务级别,脏读、幻读意思。问题回答情况:其中G1与CMS区别我只讲了G1比CMS更耗CPU,但回收更快效果更好,两者内存划分设计不同,G1更适合大内存等,具体原因及细节没讲清;脏读、幻读只回答出跟数据库事务有关,面试当时忘记了具体什么叫脏读,什么叫幻读,有点分不清。这两个好像都没有答好,然后面试官问了我待遇期望。二面:
原文链接:http://blog.csdn.net/taiyang1987912/article/details/29271549关于堆栈不清楚的可以参考这篇文章:http://blog.csdn.net/c_base_jin/article/details/25558929 一、简介 Qt内存管理机制:Qt在内部能够维护对象的层次结构。对于可视元素,这种层次结构就是子组件与父组件的关系;对于非可视元素,则是一个对象与另一个对象的从属关系。在Qt中,在Qt中,删除父对象会将其子对象一起删除。 C++中delete和new必须配对使用(一一对应):delete少了,则内存泄露,多了麻烦更大。Qt中使用了new却很少delete,因为QObject的类及其继承的类,设置了parent(也可在构造时使用setParent函数或parent的addChild)故parent被delete时,这个parent的相关所有child都会自动delete,不用用户手动处理。但parent是不区分它的child是new出来的还是在栈上分配的。这体现delete的强大,可以释放掉任何的对象,而del
系统信息 arch显示机器的处理器架构(1) uname-m显示机器的处理器架构(2) uname-r显示正在使用的内核版本 dmidecode-q显示硬件系统部件-(SMBIOS/DMI) hdparm-i/dev/hda罗列一个磁盘的架构特性 hdparm-tT/dev/sda在磁盘上执行测试性读取操作 cat/proc/cpuinfo显示CPUinfo的信息 cat/proc/interrupts显示中断 cat/proc/meminfo校验内存使用 cat/proc/swaps显示哪些swap被使用 cat/proc/version显示内核的版本 cat/proc/net/dev显示网络适配器及统计 cat/proc/mounts显示已加载的文件系统 lspci-tv罗列PCI设备 lsusb-tv显示USB设备 date显示系统日期 cal2007显示2007年的日历表 date0412170020
在使用node-canvas时,由于更换了node版本遇到 Error:Themodule'\\?\D:\nodejs\node_modules\canvas\build\Release\canvas.node'wascompiledagainstadifferentNode.jsversionusingNODE_MODULE_VERSION83.ThisversionofNode.jsrequiresNODE_MODULE_VERSION72.Pleasetryre-compilingorre-installingthemodule(forinstance,using`npmrebuild`or`npminstall`). 解决方法: 重新安装使用cnpminstallcanvas(不要使用npm或yarn安装,安装过几次都失败了) 或者从https://github.com/node-gfx/node-canvas-prebuilt/releases直接下载编译好的包,替换掉build\Release 说明: NODE_MODULE_VERSION83对应nodejs版
三、四元数到欧拉角的转换arctan和arcsin的结果是,这并不能覆盖所有朝向(对于角的取值范围已经满足),因此需要用atan2来代替arctan。四、在其他坐标系下使用在其他坐标系下,需根据坐标轴的定义,调整一下以上公式。如在Direct3D中,笛卡尔坐标系的X轴变为Z轴,Y轴变为X轴,Z轴变为Y轴(无需考虑方向)。2.2.3四元数计算出欧拉角的程序设计floatq0=1,q1=0,q2=0,q3=0;//定义四元素voidIMU_Update(void){floatnorm; floatgx=MPU6500_Gyro.X * GYRO_GR,gy=MPU6500_Gyro.Y * GYRO_GR,gz=MPU6500_Gyro.Z * GYRO_GR;//角度之间的单位转换floatax=Acc_Avg.X,ay=Acc_Avg.Y,az=Acc_Avg.Z;floatq0q0=q0*q0;floatq0q1=q0*q1;floatq0q2=q0*q2;floatq1q1=q1*q1;floatq1q3=q1*q3;floatq2q2=q2 *q2;floatq2q3=q2 *
1、顺序串 实现的操作有: 构造串 判断空串 返回串的长度 返回位序号为i的字符 将串的长度扩充为newCapacity 返回从begin到end-1的子串 在第i个字符之前插入字串str 删除子串 在实现返回位序号从begin到end-1的子串时,注意,此处串的起始位置为0,同时为了方便,我们再次没有新建一个变量,而是返回一个string,可以直接输出,在main函数中可以看到。 通过string.indexof()函数将字符数组转化为字符串。 同时在实现每个字符串的操作之前,先进行异常处理,避免出现越界现象。 curlen:表示当前字符串的长度 str:使用字符数组存放串值 1packageMain; 2/*串的操作 3**/ 4publicclassMain{ 5publicchar[]str;//使用字符数组存放串值 6publicstaticintcurlen;//当前字符串的长度 7publicMain() 8{ 9str=newchar[0]; 10curlen=0; 11} 12//以字符串常量构造串 13publicMain(Stringstring
1、查看python安装目录 window:wherepython linux:whereispython 2、查看pip安装了哪些库或者包 piplist piplist-o #查看可升级的包/库 3、查看某个包、库的安装路径 pip安装完包后,再执行一次命令pipinstallxx,就会显示安装路径。 比如安装requests后,可以再次pipinstallrequests查看requests的安装路径。 4、pip安装的包/库位于: python安装路径\lib\site-packages中 注:python3的可能需要使用pip3(不绝对,如果电脑只有python3,pip和pip3应该都行) 5、查看某个包/库的信息 pipshowxxx 如pipshowrequests,用于查看requests库的名字、版本等信息 pipshow-fxxx #查看指定包的详细信息 6、查看pip 的版本 pip-V 或者 pip--version 不仅可以查看pip的版本,还可以查看
除了几乎所有语言都支持的简单内置类型(比如整型和浮点型)外,go语言也内置了一些比较新的语言中内置的高级类型,比如c#和java中的数组和字符串。 go语言还内置了一个对于其他静态类型语言通常用库方式支持的字典类型, 另外有一个新增的数据类型:数组qiepian(slice)。可以认为数组切片是一种可动态增长的数组。这几种数据结构基本上覆盖了绝大部分的应用场景。数组切片的功能与c++标准库中的vector非常类似。 go语言在语言层面对数组切片的支持,相比c++开发者有效的消除了反复写一下几行代码的工作量: #include<vector> #include<map> #include<algorithm> usingnamespacestd; 因为是语言内置特性,开发者根本不需要费事去添加依赖的包,即可以少一些输入工作量,也可以让代码看