【ML】常用损失函数

Backto ML Index

Loss function 损失函数description 描述Scenes 使用问题
MAEMean Absolute Error L ( y ^ , y ) = 1 n ∑ i n ∣ y i − y i ^ ∣ L(\hat y, y)= \frac 1 n\sum_i^n{ \vert y_i - \hat {y_i} \vert} L(y^,y)=n1inyiyi^Regression
MSEMean Squared Error L ( y ^ , y ) = 1 n ∑ i n ( y i − y i ^ ) 2 L(\hat y, y)= \frac 1 n\sum_i^n{ (y_i - \hat {y_i})^2} L(y^,y)=n1in(yiyi^)2Regression
Entropy Loss L ( y ^ , y ) = − 1 n ∑ i n ( y i ln ⁡ y i ^ + ( 1 − y i ) ln ⁡ ( 1 − y i ^ ) ) L(\hat y, y)= - \frac 1 n \sum_i^n({ y_i\ln \hat {y_i}} + (1-y_i)\ln {(1-\hat{y_i})}) L(y^,y)=n1in(yilnyi^+(1yi)ln(1yi^))classification
Hinge Loss L o s s = ∑ j ≠ y i max ⁡ ( 0 , s j − s y i + 1 ) Loss = \sum_{j \neq y_i} \max (0, s_j - s_{y_i} + 1) Loss=j̸=yimax(0,sjsyi+1)classification

Cross Entropy Loss

交叉熵损失函数,完整形式为 L ( y ^ , y ) = − 1 n ∑ i ( y i ln ⁡ y i ^ + ( 1 − y i ) ln ⁡ ( 1 − y i ^ ) ) L(\hat y, y)= - \frac 1 n \sum_i({ y_i\ln \hat {y_i}} + (1-y_i)\ln {(1-\hat{y_i})}) L(y^,y)=n1i(yilnyi^+(1yi)ln(1yi^)). 当真实 label 的值 y i = 0 y_i = 0 yi=0 的情况下,前半部分消失,当 y i = 1 y_i = 1 yi=1的情况下,后半部分消失。

Cross Entropy Loss 有两个特性:

  • 非负性。我们的目标是最小化 L, 也就是逼近 0
  • 当网络输出 y ^ \hat y y^ 与 事实label y y y 很接近的时候,即准确性很高的时候,L 的值都接近 0. 非常理想的情况。

这两个特性也是我们设计 Cross Entropy Loss 的初衷。

再看BP 中的导数计算,已知
y ^ = δ ( z ) , z = ∑ i ω i x i + b \hat y = \delta(z), z = \sum_i \omega_i x_i + b y^=δ(z),z=iωixi+b
对于单个神经元而言, L ( y ^ , y ) = − ( y ln ⁡ y ^ + ( 1 − y ) ln ⁡ ( 1 − y ^ ) ) L(\hat y,y) = -(y\ln \hat y + (1-y) \ln (1-\hat y)) L(y^,y)=(ylny^+(1y)ln(1y^))

(TODO: 待补充,with Andrew Ng)

Hinge Loss

hinge loss 常用于最大间隔分类(maximum-margin classification),最常用的是SVM。
基本思路是 :在一定的安全间隔内(通常是 1),正确类别的分数应高于所有错误类别的分数之和。
Hinge Loss不可微,但它是一个凸函数,因此可以轻而易举地使用机器学习领域中常用的凸优化器。

L o s s = ∑ j ≠ y i max ⁡ ( 0 , s j − s y i + 1 ) Loss = \sum_{j \neq y_i} \max (0, s_j - s_{y_i} + 1) Loss=j̸=yimax(0,sjsyi+1)

举例:
以下是分类器在三个样本(Image #1,#2, #3)上对于三个类别(Dog/Cat/Horse)预测的结果,哪个好,哪个坏呢?通过 Hinge Loss 计算一哈
在这里插入图片描述

## 1st training example
max(0, (1.49) - (-0.39) + 1) + max(0, (4.21) - (-0.39) + 1)
max(0, 2.88) + max(0, 5.6)
2.88 + 5.6
8.48 (High loss as very wrong prediction)
## 2nd training example
max(0, (-4.61) - (3.28)+ 1) + max(0, (1.46) - (3.28)+ 1)
max(0, -6.89) + max(0, -0.82)
0 + 0
0 (Zero loss as correct prediction)
## 3rd training example
max(0, (1.03) - (-2.27)+ 1) + max(0, (-2.37) - (-2.27)+ 1)
max(0, 4.3) + max(0, 0.9)
4.3 + 0.9
5.2 (High loss as very wrong prediction)

Ref

<think>我们正在讨论如何在C#中实现机器学习中的损失函数。根据引用内容,SciSharp项目提供了在.NET中模仿Python机器学习代码的能力。特别地,引用[4]提到了损失函数,如CategoricalCrossentropy(分类交叉熵)。在C#中,我们可以使用SciSharp的TensorFlow.NET库来构建神经网络,其中包括了各种损失函数。此外,我们也可以自己实现损失函数。常见的损失函数包括:1.均方误差(MSE)-用于回归问题2.交叉熵(CrossEntropy)-用于分类问题下面我们将分别展示如何用C#实现这两个损失函数。首先,假设我们使用TensorFlow.NET,那么我们可以直接使用其内置的损失函数。例如:```csharpusingTensorflow;usingstaticTensorflow.Binding;//使用内置的均方误差损失函数varloss=tf.keras.losses.MeanSquaredError();```但是,如果我们需要自己实现,可以如下:1.均方误差(MSE)的公式为:$$MSE=\frac{1}{n}\sum_{i=1}^{n}(y_i-\hat{y_i})^2$$其中,$y_i$是真实值,$\hat{y_i}$是预测值,$n$是样本数量。2.交叉熵损失函数(以二分类为例)的公式为:$$BinaryCrossentropy=-\frac{1}{n}\sum_{i=1}^{n}[y_i\cdot\log(\hat{y_i})+(1-y_i)\cdot\log(1-\hat{y_i})]$$下面我们用C#代码实现这两个损失函数:均方误差(MSE)的实现:```csharppublicdoubleMeanSquaredError(double[]yTrue,double[]yPred){if(yTrue.Length!=yPred.Length)thrownewArgumentException("Arraysmusthavethesamelength.");doublesum=0.0;for(inti=0;i<yTrue.Length;i++){doubleerror=yTrue[i]-yPred[i];sum+=error*error;}returnsum/yTrue.Length;}```二分类交叉熵的实现:```csharppublicdoubleBinaryCrossEntropy(double[]yTrue,double[]yPred){if(yTrue.Length!=yPred.Length)thrownewArgumentException("Arraysmusthavethesamelength.");doublesum=0.0;for(inti=0;i<yTrue.Length;i++){//为了避免log(0)的情况,将预测值限制在一个很小的范围内doubleyPredClipped=Math.Max(Math.Min(yPred[i],1-1e-15),1e-15);sum+=yTrue[i]*Math.Log(yPredClipped)+(1-yTrue[i])*Math.Log(1-yPredClipped);}return-sum/yTrue.Length;}```对于多分类问题,我们通常使用分类交叉熵(CategoricalCrossentropy)。假设我们有一个二维数组,每一行代表一个样本的多个类别的预测概率,真实标签是one-hot编码。分类交叉熵的公式为:$$CategoricalCrossentropy=-\frac{1}{n}\sum_{i=1}^{n}\sum_{j=1}^{m}y_{i,j}\cdot\log(\hat{y_{i,j}})$$其中,$n$是样本数,$m$是类别数,$y_{i,j}$是第i个样本在第j个类别上的真实标签(0或1),$\hat{y_{i,j}}$是预测的概率。实现如下:```csharppublicdoubleCategoricalCrossEntropy(double[,]yTrue,double[,]yPred){if(yTrue.GetLength(0)!=yPred.GetLength(0)||yTrue.GetLength(1)!=yPred.GetLength(1))thrownewArgumentException("Arraysmusthavethesamedimensions.");intnumSamples=yTrue.GetLength(0);intnumClasses=yTrue.GetLength(1);doublesum=0.0;for(inti=0;i<numSamples;i++){for(intj=0;j<numClasses;j++){//同样,为了避免log(0)的情况,将预测值限制在一个很小的范围内doubleyPredClipped=Math.Max(Math.Min(yPred[i,j],1-1e-15),1e-15);sum+=yTrue[i,j]*Math.Log(yPredClipped);}}return-sum/numSamples;}```注意:在实际应用中,我们通常使用数值稳定的实现,并且使用向量化操作以提高效率。上述代码是为了演示目的而写的简单版本。另外,在TensorFlow.NET中,我们可以直接使用内置的损失函数,例如:```csharpvarloss=tf.keras.losses.CategoricalCrossentropy();```总结:在C#中实现损失函数,我们可以根据数学公式自己编写,也可以利用现有的库(如TensorFlow.NET)中提供的实现。使用库函数通常更高效且稳定,特别是在处理大规模数据时[^4]。如果你正在使用其他.NET机器学习库(如ML.NET),那么它们也提供了内置的损失函数。例如,在ML.NET中,我们可以通过指定评估器来选择损失函数。最后,值得注意的是,损失函数的选择取决于具体的任务(回归、二分类、多分类等)。相关问题:1.在C#中如何实现自定义的损失函数并用于TensorFlow.NET模型的训练?2.除了均方误差和交叉熵,还有哪些常用损失函数?它们在C#中如何实现?3.在C#中使用ML.NET进行机器学习时,如何指定损失函数?4.如何测试自己实现的损失函数的正确性?</think>### 在 C# 中实现机器学习损失函数 在 C# 中实现机器学习损失函数主要有两种方式:**使用现有库的内置函数**或**手动实现数学公式**。以下是具体方法和示例: --- #### 一、使用机器学习库的内置损失函数 **推荐方式**:借助 TensorFlow.NET(SciSharp 生态)或 ML.NET 的内置实现 1. **TensorFlow.NET 示例(类 Python 语法)** ```csharp using Tensorflow.Keras.Losses; // 创建交叉熵损失函数 ILossFunction categoricalCrossentropy = Losses.CategoricalCrossentropy(); // 计算损失值(y_true: 真实标签, y_pred: 预测值) Tensor loss = categoricalCrossentropy.Call( tf.constant(new float[,] { { 1, 0 }, { 0, 1 } }), // y_true (one-hot) tf.constant(new float[,] { { 0.9f, 0.1f }, { 0.4f, 0.6f } }) // y_pred ); Console.WriteLine($"损失值: {loss.numpy()}"); ``` - 支持常见损失函数:`BinaryCrossentropy`、`MeanSquaredError`、`Huber` 等[^4] 2. **ML.NET 示例(原生 .NET 库)** ```csharp using Microsoft.ML.Trainers; // 在模型训练中指定损失函数 var options = new SdcaLogisticRegressionBinaryTrainer.Options { LossFunction = new LogisticLoss() // 对数损失函数 }; var pipeline = mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(options); ``` --- #### 二、手动实现损失函数(数学公式) 适用于自定义损失或理解原理,以下是关键实现: 1. **均方误差(MSE)** $$MSE = \frac{1}{n}\sum_{i=1}^{n}(y_{true}^{(i)} - y_{pred}^{(i)})^2$$ ```csharp public float MeanSquaredError(float[] yTrue, float[] yPred) { float sum = 0; for (int i = 0; i < yTrue.Length; i++) { float diff = yTrue[i] - yPred[i]; sum += diff * diff; } return sum / yTrue.Length; } ``` 2. **交叉熵损失(分类任务)** $$CrossEntropy = -\sum_{i=1}^{C} y_{true}^{(i)} \log(y_{pred}^{(i)})$$ ```csharp public float CategoricalCrossEntropy(float[] yTrue, float[] yPred) { float loss = 0; for (int i = 0; i < yTrue.Length; i++) { // 避免 log(0) 错误 float pred = Math.Max(yPred[i], 1e-15f); loss += yTrue[i] * (float)Math.Log(pred); } return -loss; } ``` --- #### 三、最佳实践建议 1. **数值稳定性** - 添加极小值(如 `1e-15`)防止 `log(0)` 错误 - 对 Softmax 输出使用 `LogSoftmax` 技巧 2. **性能优化** ```csharp // 使用 SIMD 指令加速计算(.NET 7+) Vector<float> trueVec = new Vector<float>(yTrue); Vector<float> predVec = new Vector<float>(yPred); Vector<float> diff = trueVec - predVec; float sum = Vector.Dot(diff, diff); ``` 3. **自动微分支持** 在 TensorFlow.NET 中可结合梯度带实现自动微分: ```csharp using (var tape = tf.GradientTape()) { Tensor yPred = model(inputs); // 模型预测 Tensor loss = MyCustomLoss(yTrue, yPred); // 自定义损失 var grads = tape.gradient(loss, model.trainable_variables); } ``` --- ### 相关问题 1. 如何在自定义 C# 神经网络中集成损失函数的自动微分? 2. 哪些场景需要自定义损失函数?请举例说明 3. 对比 TensorFlow.NET 和 ML.NET 在损失函数实现上的性能差异 4. 如何为不平衡分类任务实现加权的交叉熵损失函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值