ML.NET日期时间数据归一化:基于时间T预测特征值Y的方法
Alright, let's walk through how to handle this datetime-to-regression prediction task in ML.NET—perfect for your sine function-based time series data. We'll focus on turning time values (either DateTime strings or Unix timestamps) into numerical features that a model can learn from, then build a regression model to predict your float Y value.
Step 1: Define Your Data Models
First, create classes to represent your input data and prediction output. This helps ML.NET map your data correctly:
// Represents a single row of your input data public class TimeSeriesInput { // Use this if your raw data has DateTime strings like "2019-10-18 10:00" [LoadColumn(0)] public DateTime Timestamp { get; set; } // Or use this if you're working directly with Unix timestamps (long integer) // [LoadColumn(0)] // public long UnixTime { get; set; } [LoadColumn(1)] public float YValue { get; set; } } // Represents the prediction output public class YPrediction { [ColumnName("Score")] // ML.NET uses "Score" for regression predictions by default public float PredictedY { get; set; } }
Step 2: Build a Data Processing Pipeline
The key part here is converting your time data into numerical features. Since your data follows a sine wave, using a continuous numerical representation of time (like Unix timestamps) works best—though you can also add periodic features to help the model catch the sine pattern.
Option 1: Convert DateTime to Unix Timestamp
If your raw data uses DateTime strings, add a custom mapping to convert them to Unix timestamps (seconds since 1970-01-01 UTC):
var mlContext = new MLContext(); // Load your data (adjust separator and header flag to match your file) var rawData = mlContext.Data.LoadFromTextFile<TimeSeriesInput>( path: "your_data.csv", separatorChar: '|', hasHeader: false); // Define the pipeline var pipeline = mlContext.Transforms.CustomMapping( (TimeSeriesInput input, TimeSeriesTransformed output) => { // Convert DateTime to Unix timestamp (seconds) output.UnixTime = (long)(input.Timestamp - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; }, contractName: "DateTimeToUnix") // Copy YValue to the "Label" column (required for regression training) .Append(mlContext.Transforms.CopyColumns("Label", nameof(TimeSeriesInput.YValue))) // Combine time features into a single "Features" column .Append(mlContext.Transforms.Concatenate("Features", "UnixTime")) // Choose a regression trainer (SDCA works well for simple patterns like sine waves) .Append(mlContext.Regression.Trainers.Sdca( labelColumnName: "Label", featureColumnName: "Features")); // Train the model var trainedModel = pipeline.Fit(rawData);
Don't forget to add the intermediate TimeSeriesTransformed class for the custom mapping:
public class TimeSeriesTransformed { public long UnixTime { get; set; } public float YValue { get; set; } }
Option 2: Add Periodic Features (For Sine Wave Data)
Since your data follows sin(x), explicitly adding sine and cosine features based on the time period will help the model fit the pattern better. For example, if your sine wave has a 1-hour period:
// Update the custom mapping to add periodic features var pipelineWithPeriodic = mlContext.Transforms.CustomMapping( (TimeSeriesInput input, TimeSeriesWithPeriodic output) => { long unixTime = (long)(input.Timestamp - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; double period = 3600; // 1 hour in seconds output.SinFeature = (float)Math.Sin(unixTime * 2 * Math.PI / period); output.CosFeature = (float)Math.Cos(unixTime * 2 * Math.PI / period); }, contractName: "AddPeriodicFeatures") .Append(mlContext.Transforms.CopyColumns("Label", nameof(TimeSeriesInput.YValue))) .Append(mlContext.Transforms.Concatenate("Features", "SinFeature", "CosFeature")) .Append(mlContext.Regression.Trainers.Sdca(labelColumnName: "Label", featureColumnName: "Features"));
With the corresponding intermediate class:
public class TimeSeriesWithPeriodic { public float SinFeature { get; set; } public float CosFeature { get; set; } public float YValue { get; set; } }
Step 3: Make Predictions
Once your model is trained, create a prediction engine to generate predictions for new time values:
// Create a prediction engine var predictor = mlContext.Model.CreatePredictionEngine<TimeSeriesInput, YPrediction>(trainedModel); // Example: Predict Y for a new DateTime var newTimePoint = new TimeSeriesInput { Timestamp = new DateTime(2019, 10, 18, 14, 0, 0) // If using Unix timestamps directly: // UnixTime = 1571397600 }; var prediction = predictor.Predict(newTimePoint); Console.WriteLine($"Predicted Y value: {prediction.PredictedY:F2}");
Key Notes
- If you're already working with Unix timestamps as input, skip the
CustomMappingstep and directly use theUnixTimecolumn as your feature. - For more complex time series, you might explore ML.NET's time series-specific trainers like
ForecastBySsa, but since you're doing single-point prediction based on time, a standard regression trainer is sufficient here.
内容的提问来源于stack exchange,提问作者Macko

