众所周知,UE4中的材质可以保存成资产,可以在材质编辑器中打开,通过设置材质表达式以及调用材质函数进行编辑。编辑完成后,可以设置在组件上,或者在蓝图中调用。

现在老板告诉你:我不想管理那么多材质文件,不想调用蓝图,能否用C++代码直接生成我想要的材质?
看完这篇文章你可以自信地说:OK。

一、准备知识

  • 在材质编辑器中,通过材质表达式构建的材质

    最右侧是待编辑的材质,可以看到它有各种属性节点(不是所有节点都同时有效,选择不同的材质域、混合模式、着色模型等,会开启或关闭相应的节点),每种属性的具体性质由左侧连接的材质表达式和材质函数来决定。
  • 材质编辑器中的材质函数

    带有 Input 前缀的节点表示函数输入,带有 Output 前缀的节点表示函数输出。
    其实双击点开材质函数会发现,函数内依然是一堆材质表达式,所以,构建一个材质的基本单位就是材质表达式,无非就是要确定材质表达式的类型,以及它们之间如何是连接的。 材质函数是以资产的形式加载和保存的,在蓝图中可以直接访问,在C++中需要用LoadObject的方式主动加载访问。本篇文章中没有使用UMaterialFunction(主要是没搞懂怎么用,请大神指教),而是把所有节点都展开成UMaterialExpression来实现的。
  • 材质表达式在C++中对应的类
    你会用的这个目录下的类:
    Engine/Source/Runtime/Engine/Classes/Materials

    这个目录下包含了各种材质表达式,老多了,他们都是UMaterialExpression的子孙。蓝图中的每一种材质表达式都能在这里找到相应的C++类。
  • 在C++中材质表达式的连接
    输入节点:UMaterialExpression的子类可能拥有不同数量和名字的输入节点,用FExpressionInput保存,如下:

    输出节点:没有输出节点,材质表达式(UMaterialExpression)本身就是下一个节点的输入,可以类比一个链表,链表的每个节点保存有指向上一个节点的指针。你可以看到FExpressionInput类中保存了UMaterialExpression指针,指向输入的材质表达式。
    连接示例:所以如果要连接两个材质表达式A和B,你应该把B的某个FExpressionInput中的UmaterialExpression指针置为A。即 B->LightMass.Expression = A;

二、大致思路

  1. 先用材质编辑器构建出想要的材质,或者已经有现成的材质。
  2. 将其转换为C++实现。
    注意:蓝图是基于C++封装的,所有蓝图一定能在C++中找到相应实现。在C++中实现自定义材质,其实就是用C++生成(New出对象)各种材质表达式,然后连接各节点。虽然材质球从直观的蓝图变成了不那么直观的C++代码,但它们表示的拓扑结构是一致的。
  3. 在C++中大致分为两步:(1)New出我们需要的表达式对象 (2)按编辑器中的结构去连接它们

三、代码示例

C++动态生成抠像材质

  1. 语境介绍
    UE在播放视频时,会将视频帧Buffer转换成媒体纹理,然后根据媒体纹理构建材质并应用在Mesh上,这样就可以在物体表面播放视频。而我现在想集成视频抠像功能,一个办法就是在纹理转换成材质之前,加入抠像的算法。由于整个视频组件(包括生成Mesh、创建播放器、创建媒体源、播放视频画面…)都是C++实现,所以现在需要在代码中集成自定义抠像材质。(参考文章:在 UE4 中设置色键材质)
  2. 将材质在编辑器中打开,查看我需要在C++中New哪些类?

    这是一个现成的解决方案,用蓝图实现。可以看到,最左侧输入是纹理采样(对应UMaterialExpressionTextureSample),它来自于视频媒体纹理,左下角Param指示了抠像键值(对应UMaterialExpressionVectorParameter),绿幕抠像RGB值则是(0.0, 1.0, 0.0)。点开材质函数可以看到:

    VectorLength也是材质函数,点开可以看到里面有一个常量和两个Distance:

    这里有相当多的节点需要我们去实现。依次查看节点类型,可以发现有材质表达式常量(对应UMaterialExpressionConstant),有材质表达式相减(对应UMaterialExpressionSubtract),有材质表达式自定义ExtractColor(对应UMaterialExpressionCustom),等等。
  3. 转换成C++代码
    在我的组件中,创建媒体纹理和通过纹理创建动态材质实例主要通过 CreateMediaMaterial 和 CreateMaterialFromTexture(创建抠像材质的实现在此函数中,重点关注此函数) 这两个函数实现。
  • CreateMediaMaterial
void UPXVideoComponent::CreateMediaMaterial()
{FString MediaTextureAssetName = GetOwner()->GetFName().ToString() + TEXT("_VideoTexture");EObjectFlags theFlags = (RF_Public | RF_Transactional);MediaTexture = NewObject<UMediaTexture>(this, UMediaTexture::StaticClass(), *MediaTextureAssetName, theFlags);MediaTexture->UpdateResource();MediaTexture->SetMediaPlayer(MediaPlayer);UTexture* theTexture = Cast<UTexture>(MediaTexture);// 通过以下函数由媒体纹理生成媒体材质,在此函数中实现材质的自定义UObject* theMatObj = CreateMaterialFromTexture(theTexture);UMaterialInterface* MediaTextureMat = Cast<UMaterialInterface>(theMatObj);MediaDynamicMaterial = VideoMeshComponent->CreateAndSetMaterialInstanceDynamicFromMaterial(0, MediaTextureMat);MediaDynamicMaterial->SetScalarParameterValue("Enable Video Alpha", 0.0f);MediaDynamicMaterial->SetScalarParameterValue("Enable Video Texture", 1.0f);MediaDynamicMaterial->SetTextureParameterValue(FName(TEXT("VideoTexture")), theTexture);
}
  • CreateMaterialFromTexture(重点)
UObject* UPXVideoComponent::CreateMaterialFromTexture(UTexture* UnrealTexture)
{FString MediaMaterialAssetName = UnrealTexture->GetFName().ToString() + TEXT("_Mat");EObjectFlags theFlags = (RF_Public | RF_Transactional);UMaterial* UnrealMaterial = nullptr;UPackage* Package = nullptr;UnrealMaterial = NewObject<UMaterial>(this, UMaterial::StaticClass(), *MediaMaterialAssetName, theFlags);const int X = -340;const int Y = 0;// Create a new texture sample expression, // this is our texture input node into the material output.// [ 对应材质表达式纹理采样 ]UMaterialExpressionTextureSample* UnrealTextureExpression = NewObject<UMaterialExpressionTextureSample>(UnrealMaterial);UnrealTextureExpression->Texture = UnrealTexture;UnrealTextureExpression->AutoSetSampleType();UnrealTextureExpression->MaterialExpressionEditorX += X;UnrealTextureExpression->MaterialExpressionEditorY += Y;UnrealMaterial->Expressions.Add(UnrealTextureExpression);UnrealMaterial->EmissiveColor.Expression = UnrealTextureExpression;UnrealMaterial->SetShadingModel(EMaterialShadingModel::MSM_Unlit);if (bEnableKeying){// Chroma_Key_Alpha (Simplified)// - Prepare for connection.// [ 对应材质表达式向量参数 ]UMaterialExpressionVectorParameter* ChromaParam = NewObject<UMaterialExpressionVectorParameter>(UnrealMaterial);ChromaParam->DefaultValue.R = float(ChromaColor.R * 1.0f / 255.0f);ChromaParam->DefaultValue.G = float(ChromaColor.G * 1.0f / 255.0f);ChromaParam->DefaultValue.B = float(ChromaColor.B * 1.0f / 255.0f);// [ 对应材质表达式常量 ]UMaterialExpressionConstant* ConstantLumaMask = NewObject<UMaterialExpressionConstant>(UnrealMaterial);ConstantLumaMask->R = 2.0f;FString ShaderCode = TEXT("float Luma = dot(Color, 1); \float ColorMask = exp(-Luma * 2 * PI / LumaMask); \Color = lerp(Color, Luma, ColorMask); \return Color / (dot(Color, 2));");FCustomInput Color;Color.InputName = FName(TEXT("Color"));FCustomInput LumaMask;LumaMask.InputName = FName(TEXT("LumaMask"));// [ 对应材质表达式自定义 ]UMaterialExpressionCustom* ExtractColor_Chroma = NewObject<UMaterialExpressionCustom>(UnrealMaterial);ExtractColor_Chroma->Code = ShaderCode;ExtractColor_Chroma->Inputs.Empty();ExtractColor_Chroma->Inputs.Add(Color);ExtractColor_Chroma->Inputs.Add(LumaMask);ExtractColor_Chroma->OutputType = ECustomMaterialOutputType::CMOT_Float3;ExtractColor_Chroma->Desc = TEXT("ExtractColor");// [ 对应材质表达式自定义 ]UMaterialExpressionCustom* ExtractColor_Image = NewObject<UMaterialExpressionCustom>(UnrealMaterial);ExtractColor_Image->Code = ShaderCode;ExtractColor_Image->Inputs.Empty();ExtractColor_Image->Inputs.Add(Color);ExtractColor_Image->Inputs.Add(LumaMask);ExtractColor_Image->OutputType = ECustomMaterialOutputType::CMOT_Float3;ExtractColor_Image->Desc = TEXT("ExtractColor");// [ 对应材质表达式相减 ]UMaterialExpressionSubtract* Subtract = NewObject<UMaterialExpressionSubtract>(UnrealMaterial);// [ 对应材质表达式常量 ]UMaterialExpressionConstant* ConstantZero = NewObject<UMaterialExpressionConstant>(UnrealMaterial);ConstantZero->R = 0.0f;// [ 对应材质表达式距离 ]UMaterialExpressionDistance* Distance = NewObject<UMaterialExpressionDistance>(UnrealMaterial);// - Graph node connection.// 开始连接各个材质表达式,拓扑结构和材质编辑器中展现的结构保持一致Distance->A.Expression = ConstantZero;Distance->B.Expression = Subtract;Subtract->A.Expression = ExtractColor_Chroma;Subtract->B.Expression = ExtractColor_Image;ExtractColor_Chroma->Inputs[0].Input.Expression = ChromaParam;ExtractColor_Chroma->Inputs[1].Input.Expression = ConstantLumaMask;ExtractColor_Image->Inputs[0].Input.Expression = UnrealTextureExpression;ExtractColor_Image->Inputs[1].Input.Expression = ConstantLumaMask;UnrealMaterial->Expressions.Add(Distance);UnrealMaterial->OpacityMask.Expression = Distance;UnrealMaterial->BlendMode = EBlendMode::BLEND_Masked;}UnrealMaterial->PostLoad();return UnrealMaterial;
}
  • CreateMaterialFromTextureV2(升级版实现 自动抠像 抠像效果更佳)
UObject* UPXVideoComponent::CreateMaterialFromTextureV2(UTexture* UnrealTexture)
{FString MediaMaterialAssetName = UnrealTexture->GetFName().ToString() + TEXT("_Mat");EObjectFlags theFlags = (RF_Public | RF_Transactional);UMaterial* UnrealMaterial = nullptr;UnrealMaterial = NewObject<UMaterial>(this, UMaterial::StaticClass(), *MediaMaterialAssetName, theFlags);const int X = -340;const int Y = 0;// Create a new texture sample expression, UMaterialExpressionTextureCoordinate* UVs = NewObject<UMaterialExpressionTextureCoordinate>(UnrealMaterial);UVs->CoordinateIndex = 0;UVs->UTiling = 1.0f;UVs->VTiling = 1.0f;UMaterialExpressionTextureSampleParameter2D* Video = NewObject<UMaterialExpressionTextureSampleParameter2D>(UnrealMaterial);Video->SamplerType = EMaterialSamplerType::SAMPLERTYPE_External;Video->Texture = UnrealTexture;Video->Coordinates.Expression = UVs;Video->MaterialExpressionEditorX += X;Video->MaterialExpressionEditorY += Y;UnrealMaterial->Expressions.Add(Video);UnrealMaterial->EmissiveColor.Expression = Video;UnrealMaterial->SetShadingModel(EMaterialShadingModel::MSM_Unlit);if (bEnableKeying){// M_CPCutout// - Prepare for connection// -- Emissive ColorUMaterialExpressionComponentMask* Mask_R = NewObject<UMaterialExpressionComponentMask>(UnrealMaterial);Mask_R->R = 1;Mask_R->G = 0;Mask_R->B = 0;Mask_R->A = 0;UMaterialExpressionComponentMask* Mask_G = NewObject<UMaterialExpressionComponentMask>(UnrealMaterial);Mask_G->R = 0;Mask_G->G = 1;Mask_G->B = 0;Mask_G->A = 0;UMaterialExpressionComponentMask* Mask_B = NewObject<UMaterialExpressionComponentMask>(UnrealMaterial);Mask_B->R = 0;Mask_B->G = 0;Mask_B->B = 1;Mask_B->A = 0;UMaterialExpressionAdd* Add = NewObject<UMaterialExpressionAdd>(UnrealMaterial);UMaterialExpressionDivide* Divide = NewObject<UMaterialExpressionDivide>(UnrealMaterial);Divide->ConstB = 2.0f;UMaterialExpressionIf* If = NewObject<UMaterialExpressionIf>(UnrealMaterial);UMaterialExpressionAppendVector* Append_0 = NewObject<UMaterialExpressionAppendVector>(UnrealMaterial);UMaterialExpressionAppendVector* Append_1 = NewObject<UMaterialExpressionAppendVector>(UnrealMaterial);// -- Opacity MaskUMaterialExpressionTextureObject* TextureObject = NewObject<UMaterialExpressionTextureObject>(UnrealMaterial);TextureObject->SamplerType = EMaterialSamplerType::SAMPLERTYPE_External;TextureObject->Texture = UnrealTexture;UMaterialExpressionTextureCoordinate* TextureCoordinate = NewObject<UMaterialExpressionTextureCoordinate>(UnrealMaterial);TextureCoordinate->CoordinateIndex = 0;TextureCoordinate->UTiling = 1.0f;TextureCoordinate->VTiling = 1.0f;UMaterialExpressionConstant2Vector* Constant2Vector = NewObject<UMaterialExpressionConstant2Vector>(UnrealMaterial);Constant2Vector->R = 0.0f;Constant2Vector->G = 0.0f;FString CustomCode = TEXT("Tex.Load(int3(Coordinate,0))");FCustomInput Tex;Tex.InputName = FName(TEXT("Tex"));FCustomInput UV;UV.InputName = FName(TEXT("UV"));FCustomInput Coordinate;Coordinate.InputName = FName(TEXT("Coordinate"));UMaterialExpressionCustom* Custom = NewObject<UMaterialExpressionCustom>(UnrealMaterial);Custom->Code = CustomCode;Custom->Inputs.Empty();Custom->Inputs.Add(Tex);Custom->Inputs.Add(UV);Custom->Inputs.Add(Coordinate);Custom->OutputType = ECustomMaterialOutputType::CMOT_Float3;Custom->Desc = TEXT("Custom");UMaterialExpressionVectorParameter* AlphaThresOffset = NewObject<UMaterialExpressionVectorParameter>(UnrealMaterial);AlphaThresOffset->ParameterName = "AlphaThresOffset";AlphaThresOffset->DefaultValue.R = 1.0f;AlphaThresOffset->DefaultValue.G = 0.0f;AlphaThresOffset->DefaultValue.B = 0.0f;AlphaThresOffset->DefaultValue.A = 1.0f;UMaterialExpressionComponentMask* AlphaThresOffset_Mask = NewObject<UMaterialExpressionComponentMask>(UnrealMaterial);AlphaThresOffset_Mask->R = 1;AlphaThresOffset_Mask->G = 1;AlphaThresOffset_Mask->B = 0;AlphaThresOffset_Mask->A = 0;UMaterialExpressionVectorParameter* WeightsRB = NewObject<UMaterialExpressionVectorParameter>(UnrealMaterial);WeightsRB->ParameterName = "WeightsRB";WeightsRB->DefaultValue.R = 0.5f;WeightsRB->DefaultValue.G = 0.5f;WeightsRB->DefaultValue.B = 0.0f;WeightsRB->DefaultValue.A = 1.0f;UMaterialExpressionComponentMask* WeightsRB_Mask = NewObject<UMaterialExpressionComponentMask>(UnrealMaterial);WeightsRB_Mask->R = 1;WeightsRB_Mask->G = 1;WeightsRB_Mask->B = 0;WeightsRB_Mask->A = 0;UMaterialExpressionVectorParameter* ClipBW = NewObject<UMaterialExpressionVectorParameter>(UnrealMaterial);ClipBW->ParameterName = "ClipBW";ClipBW->DefaultValue.R = 0.0f;ClipBW->DefaultValue.G = 1.0f;ClipBW->DefaultValue.B = 0.0f;ClipBW->DefaultValue.A = 1.0f;UMaterialExpressionComponentMask* ClipBW_Mask = NewObject<UMaterialExpressionComponentMask>(UnrealMaterial);ClipBW_Mask->R = 1;ClipBW_Mask->G = 1;ClipBW_Mask->B = 0;ClipBW_Mask->A = 0;UMaterialExpressionScalarParameter* Unpremult = NewObject<UMaterialExpressionScalarParameter>(UnrealMaterial);Unpremult->DefaultValue = 0.0f;FString ColorDiffKeyerCode = TEXT("const float epsilon = 0.001; \float diffGR = max(KeyColor.g - KeyColor.r, epsilon); \float diffGB = max(KeyColor.g - KeyColor.b, epsilon); \float diff = min(diffGR, diffGB); \float weightedRB = GreenScreen.g - (GreenScreen.r * WeightsRB.x + GreenScreen.b * WeightsRB.y); \float alpha = weightedRB / diff; \alpha /= AlphaThresOffset.x; \alpha = (alpha - ClipBW.x) / (ClipBW.y - ClipBW.x); \alpha = saturate((alpha - AlphaThresOffset.y) / (1.0 - AlphaThresOffset.y)); \alpha = 1.0 - alpha; \float3 rgb = lerp(GreenScreen, GreenScreen * alpha, Unpremult); \return float4(rgb, alpha);");FCustomInput GreenScreenInput;GreenScreenInput.InputName = FName(TEXT("GreenScreen"));FCustomInput KeyColorInput;KeyColorInput.InputName = FName(TEXT("KeyColor"));FCustomInput AlphaThresOffsetInput;AlphaThresOffsetInput.InputName = FName(TEXT("AlphaThresOffset"));FCustomInput WeightsRBInput;WeightsRBInput.InputName = FName(TEXT("WeightsRB"));FCustomInput ClipBWInput;ClipBWInput.InputName = FName(TEXT("ClipBW"));FCustomInput UnpremultInput;UnpremultInput.InputName = FName(TEXT("Unpremult"));UMaterialExpressionCustom* ColorDiffKeyer = NewObject<UMaterialExpressionCustom>(UnrealMaterial);ColorDiffKeyer->Code = ColorDiffKeyerCode;ColorDiffKeyer->Inputs.Empty();ColorDiffKeyer->Inputs.Add(GreenScreenInput);ColorDiffKeyer->Inputs.Add(KeyColorInput);ColorDiffKeyer->Inputs.Add(AlphaThresOffsetInput);ColorDiffKeyer->Inputs.Add(WeightsRBInput);ColorDiffKeyer->Inputs.Add(ClipBWInput);ColorDiffKeyer->Inputs.Add(UnpremultInput);ColorDiffKeyer->OutputType = ECustomMaterialOutputType::CMOT_Float4;ColorDiffKeyer->Desc = TEXT("ColorDiffKeyer");UMaterialExpressionComponentMask* ColorDiffKeyer_Mask = NewObject<UMaterialExpressionComponentMask>(UnrealMaterial);ColorDiffKeyer_Mask->R = 0;ColorDiffKeyer_Mask->G = 0;ColorDiffKeyer_Mask->B = 0;ColorDiffKeyer_Mask->A = 1;// - Graph node connection.// -- Emissive ColorMask_R->Input.Expression = Video;Mask_G->Input.Expression = Video;Mask_B->Input.Expression = Video;Add->A.Expression = Mask_R;Add->B.Expression = Mask_B;Divide->A.Expression = Add;If->A.Expression = Mask_G;If->B.Expression = Divide;If->AGreaterThanB.Expression = Divide;If->AEqualsB.Expression = Mask_G;If->ALessThanB.Expression = Mask_G;Append_0->A.Expression = Mask_R;Append_0->B.Expression = If;Append_1->A.Expression = Append_0;Append_1->B.Expression = Mask_B;UnrealMaterial->Expressions.Add(Append_1);UnrealMaterial->EmissiveColor.Expression = Append_1;// -- Opacity MaskCustom->Inputs[0].Input.Expression = TextureObject;Custom->Inputs[1].Input.Expression = TextureCoordinate;Custom->Inputs[2].Input.Expression = Constant2Vector;AlphaThresOffset_Mask->Input.Expression = AlphaThresOffset;WeightsRB_Mask->Input.Expression = WeightsRB;ClipBW_Mask->Input.Expression = ClipBW;ColorDiffKeyer->Inputs[0].Input.Expression = Video; // GreenScreenColorDiffKeyer->Inputs[1].Input.Expression = Custom; // KeyColorColorDiffKeyer->Inputs[2].Input.Expression = AlphaThresOffset_Mask; // AlphaThresOffsetColorDiffKeyer->Inputs[3].Input.Expression = WeightsRB_Mask; // WeightsRBColorDiffKeyer->Inputs[4].Input.Expression = ClipBW_Mask; // ClipBWColorDiffKeyer->Inputs[5].Input.Expression = Unpremult; // UnpremultColorDiffKeyer_Mask->Input.Expression = ColorDiffKeyer;UnrealMaterial->Expressions.Add(ColorDiffKeyer_Mask);UnrealMaterial->OpacityMask.Expression = ColorDiffKeyer_Mask;UnrealMaterial->BlendMode = EBlendMode::BLEND_Masked;}UnrealMaterial->PostLoad();UE_LOG(LogVideo, Log, TEXT("[PXVideoComponent] Media material(%s) created. Keying(%d). Translucency(%d)"), *UnrealMaterial->GetFName().ToString(), bEnableKeying, bEnableTranslucency);return UnrealMaterial;
}

四、自定义材质效果

代码中 bEnableKeying = false 对比 bEnableKeying = true
bEnableKeying = false:

bEnableKeying = true:

五、参考

https://zhuanlan.zhihu.com/p/86302046

UE4 用C++构建自定义材质 完成视频抠像相关推荐

  1. UE4最简单的方法实现视频抠像

    网上看了别人的视频抠像教程,感觉写的很复杂,不过我感觉视频抠像并不是一件复杂的事情,所以,我今天就写了这篇教程,用最简单的方法实现视频抠像效果,相信大家一看就会 先看效果图: 首先准备一个视频 使用P ...

  2. 使用 Yocto Project 构建自定义嵌入式 Linux 发行版

    使用 Yocto Project 构建自定义嵌入式 Linux 发行版 转自: http://zzjlzx.blog.chinaunix.net/uid-9688646-id-5175371.html ...

  3. Qt 3D:高级自定义材质QML示例

    Qt自带集成开发环境(IDE),名为Qt Creator.它可以在Linux.OS X和Windows上运行,并提供智能代码完成.语法高亮.集成帮助系统.调试器和剖析器集成,还集成了所有主要的版本控制 ...

  4. ZEGO教程:如何通过electron构建桌面跨平台音视频应用

    近年来,视频直播.短视频.在线教育.在线医疗.人工智能.以及VR等视频领域的相关行业都非常热门,成为大众瞩目的焦点.而5G网络的相继普及,移动网速飞速提升,又将引起下一轮视频应用的革命. 可以看到,在 ...

  5. Unity Shader 学习笔记(5)Shader变体、Shader属性定义技巧、自定义材质面板

    写在之前 Shader变体.Shader属性定义技巧.自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用 ...

  6. 使用自定义材质球,实现NGUI屏幕溶解和灰显

    UITexture实现的溶解: 重设UITeture的材质球实现上述效果,把当前屏幕渲染的Texture2D丢给UITexture,即可实现UI屏幕特效,背景模糊等都可以. 难点主要是实时刷新问题 解 ...

  7. R语言使用ggplot2包使用geom_violin函数绘制分组小提琴图(构建自定义函数配置显示均值、标准偏差)实战

    R语言使用ggplot2包使用geom_violin函数绘制分组小提琴图(构建自定义函数配置显示均值.标准偏差)实战 目录

  8. sklearn基于make_scorer函数为Logistic模型构建自定义损失函数并可视化误差图(lambda selection)和系数图(trace plot)+代码实战

    sklearn基于make_scorer函数为Logistic模型构建自定义损失函数并可视化误差图(lambda selection)和系数图(trace plot)+代码实战 # 自定义损失函数 i ...

  9. sklearn基于make_scorer函数为Logistic模型构建自定义损失函数+代码实战(二元交叉熵损失 binary cross-entropy loss)

    sklearn基于make_scorer函数为Logistic模型构建自定义损失函数+代码实战(二元交叉熵损失 binary cross-entropy loss) # 广义线性模型中的各种连接函数: ...

最新文章

  1. unix更喜欢进程,可是...
  2. sdn智能互联系统及开发平台_聊天交友平台系统APP开发
  3. doc转docx文件会乱吗_Word文档doc与docx的区别
  4. [蓝桥] 算法提高 扶老奶奶过街
  5. CodeForces - 551C GukiZ hates Boxes(二分+贪心)
  6. N-甲基-N-亚硝基脲(MNU)与眼睛健康(思考中)
  7. android 发送广播_从0系统学Android--5.2 发送广播
  8. Linux 汇编学习
  9. ios---NSNotificationCenter传值
  10. SpringBoot 的属性配置文件
  11. Java入门:JDK与Eclipse之类的集成开发工具的关系
  12. tomcat设置子域名session共享以及修改JSESSIONID
  13. go语言介绍及应用场景分析
  14. 计算机office demo,办公软件应用(Office2007)中级_DEMO盘-2013
  15. 团队作业8----第二次项目冲刺(Beta阶段) 第五天
  16. 小米笔记本ubantu20.04安装输入法和Nvidia驱动 实录
  17. S3DIS数据集的几个bug
  18. Gradle本地化构建技巧之自定义Gradle配置文件
  19. cpu性能指标和测试工具
  20. 物联网技术的应用领域

热门文章

  1. c# 桌面录屏,生成视频方案总结
  2. 想考阿里云acp证书,报哪个机构好?
  3. 千年疑惑:为什么我越累越失眠,越睡越疲惫?
  4. Spring Boot 学习[一] 介绍与入门
  5. ec20 以太网_整车通讯系统——车载以太网系统系列文章(第一篇)
  6. Java - io输入输出流 --转换流
  7. 大数据竞赛-----DC竞赛ANC
  8. 【css】css动画实现的3种方式
  9. cPanel WHM 安装教程
  10. 带条码打印的固定资产管理系统源码