今日已更新 88 条资讯 | 累计 40862 条内容
关于我们

标签:#Data

找到 865 篇相关文章

AI 资讯

Why Spark Couldn't Read from Kafka: A Real Debugging Journey Across PySpark, Hadoop, Docker, and Kafka

I thought this would be a simple task. I already had a Python Kafka producer running. Kafka was up in Docker. The topic existed, and I could send a message into it successfully. The next step sounded straightforward: Python Producer ↓ Kafka ↓ Spark Structured Streaming All I wanted Spark to do was read a JSON message from a Kafka topic. Instead, I ran into one error after another. At first, it looked like one problem: Spark cannot read Kafka. It was not one problem. It turned into a chain of failures across several different layers: Python / PySpark ↓ Spark runtime ↓ Kafka connector ↓ Hadoop / Windows ↓ Docker ↓ Kafka networking ↓ Ivy dependency resolution The useful part of this experience was not any single fix. It was learning how to separate the layers and stop treating every error as a problem in my Python code. This is the full debugging path. What I Was Building This was part of an financial data engineering project. The batch side of the project already looked roughly like this: Financial Data Source ↓ Python ingestion ↓ AWS S3 ↓ Snowflake ↓ dbt ↓ Financial anomaly models I wanted to add a streaming extension for newly arriving financial events. For the first version, I kept it intentionally simple: Python Kafka Producer ↓ Kafka topic: financial_events ↓ Spark Structured Streaming The producer sent a simulated financial event: { "company_id" : "COMPANY_001" , "company_name" : "Sample Company" , "report_type" : "quarterly_report" , "reporting_date" : "2026-08-08" , "event_id" : "FIN-20260808-001" , "source" : "simulated_financial_event" } Kafka accepted the message successfully. I could even read it with Kafka's console consumer. So Kafka itself was working. Then Spark entered the picture. Failure #1: PySpark Worked, but spark-submit Didn't I installed PySpark: pip install pyspark Then I installed Java 17 and verified it: java -version After reopening my terminal, Java was available. I tested Spark directly through Python: python -c "from pyspark.sql import S

2026-08-10 原文 →
AI 资讯

35 domains link to every major web host

we compared 8 web hosts in common crawl's domain-level link graph. 35 non-platform domains link to all 8, while 72% of linking domains appear for only one subject. how we pulled this for each subject domain, we pulled the top 2,000 referring domains by authority from common crawl release Apr-Jun 2026 (cc-main-2026-apr-may-jun). we intersected those lists, then removed platform, cdn, social, and other non-editorial domains from the clean overlap counts. the filter matters. hosting providers, cdns, url shorteners and the big social networks link to almost everything, so leaving them in would produce a universal list that is technically correct and useless for outreach. the counts below are after that filter unless a column says otherwise. everything here comes from the open common crawl webgraph, so you can reproduce it without a paid backlink tool. subject domains domain referring domains cg authority hostinger.com 36,900 61 siteground.com 13,882 60 bluehost.com 48,747 61 dreamhost.com 36,470 61 wpengine.com 100,000 64 cloudways.com 13,795 58 kinsta.com 13,963 62 namecheap.com 16,701 62 the overlap across the 8 subjects, we found 10,077 unique linking domains. the clean universal set contains 35 domains. metric value unique linking domains 10,077 link to one subject 72% link to all 8 35 overlap distribution overlap all domains non-platform link to all 8 42 35 link to 7 89 86 link to 6 133 131 link to 5 185 182 link to 4 336 335 link to 3 614 608 link to 2 1,432 1,430 link to just 1 7,246 7,240 the distribution is the interesting part. most linking domains sit in the bottom row: they mention one product and never come back. the rows above it are where outreach lives, because a site that already covers several products in a category has an editorial reason to cover another one. a short universal list usually means the category is covered by a handful of directories, review sites and integration hubs rather than by a broad press base. a long one means the category has r

2026-08-10 原文 →
AI 资讯

Idempotency Keys: Designing APIs That Survive Retries

Every API that sits behind an unreliable network eventually faces the same problem: a client sends a request, the connection drops before the response arrives, and the client has no idea whether the operation happened. Did the payment go through? Did the order get created twice? The client's only safe move is to retry — which means your server needs a story for what happens when the same "create this thing" request arrives more than once. That story is idempotency keys, and getting the details right is more subtle than it first looks. The core idea The client generates a unique token — typically a UUID — once per logical operation, and attaches it to every retry of that operation: POST /orders Idempotency-Key: 7c3fd9a2-df01-4b3e-9a55-1e5f9b6b6d55 {"sku": "WIDGET-1", "qty": 2} The server's job is to guarantee that no matter how many times a request with that key arrives, the side effect (charging a card, creating an order, sending an email) happens at most once, and every retry gets back the same response the original request would have produced. Note what this is not: it is not deduplicating by request body. Two requests with identical bodies but no key are legitimately two different orders for two widgets. The key is what marks them as "the same attempt," not the payload. The naive approach, and why it breaks A common first pass is a table like: CREATE TABLE idempotency_keys ( key TEXT PRIMARY KEY , response_body JSONB , status_code INT ); On each request: check if the key exists, and if so return the cached response; otherwise do the work and insert the result. This looks right and is wrong in a specific way: it has a race condition. Two retries can arrive concurrently (a client that timed out and fired a second attempt while the first was still in flight), both miss the cache check, and both execute the underlying operation. You've now charged the card twice. Making the check-and-do atomic The fix is to claim the key before doing the work, using the database's ow

2026-08-10 原文 →
AI 资讯

A backup you haven't restored isn't a backup

Migrating from MongoDB Atlas to a self-hosted replica set bought us control and cut our bill. It also quietly removed something we had stopped thinking about: Atlas had been taking continuous backups for us the entire time. After the migration, production data for Prochesta lived in /var/db/mongo on a single VPS. No snapshots. No off-box copy. A rm -rf , a bad migration script, or a dead disk would have been the end of it. We had written "backups" as a follow-up task in the migration spec, which is the engineering equivalent of a sticky note on a bank vault. The requirement we actually cared about was narrower than "back up the database". Most real-world data loss at our scale isn't hardware failure — it's a deploy that writes garbage, or someone running an update without a filter. Recovering to last night doesn't help when the damage happened at 14:20 and you noticed at 14:50. We needed to recover to an arbitrary moment , not to a nightly snapshot. The constraint nobody mentions: Community has no $backupCursor We chose Percona Backup for MongoDB (PBM), and immediately hit the limitation that shapes every decision downstream. PBM offers physical backups — fast file-level copies that restore in minutes and barely touch the running server. They work by opening a backup cursor via the $backupCursor aggregation stage. That stage exists in Percona Server for MongoDB and in MongoDB Enterprise. It does not exist in MongoDB Community, which is what the official mongo:8.0 image ships. So on Community, PBM gives you logical backups only: every document read out through mongod , compressed, and shipped off-box. Two consequences, both accepted deliberately rather than discovered later: Backups cost CPU on the primary — and with a single-member replica set there's no secondary to offload the read to. Restores insert documents and rebuild indexes, so restore time grows with data size much faster than backup time does. At our current size that's minutes, not hours. It's also the t

2026-08-10 原文 →
AI 资讯

AmaliTech Apprenticeship Program (AAP) (AAP)

AmaliTech Apprenticeship Program (AAP) launched in November 2025, with its first cohort starting on November 17th, 2025. It is self-paced, meaning apprentices move through the curriculum at their own speed rather than following a fixed lesson-by-lesson schedule, though attendance in the office is still required. It offers 5+ specializations, including Fullstack Development (Node.js/NestJS and React/Next.js or Angular), Python Backend & AI App Development, Backend Development with Java, Data Engineering, DevOps, and Quality Assurance. There are two entry paths, entry-level and mid-level, based on experience, and each spends a different amount of time in the program: entry-level apprentices spend 6–9 months, while mid-level apprentices spend 4–6 months. The program is intense: apprentices are required to be in the office 10 hours a day, Monday through Friday. In return, it offers solid compensation. Entry-level apprentices receive a stipend of 250k+ RWF, and mid-level apprentices receive 500k+ RWF. That's the program itself. So how do you actually join? Eligibility The biggest requirement: since this is an in-person program, you need to already be based in Rwanda or be willing to relocate. A background in software development. The Application Process Apply. Applications open every three months. Cohorts have run in November 2025, March 2026, June 2026, and September 2026, so you can expect the pattern to continue. Screening, then two assessments. If you pass the screening stage, you move on to: General Coding Assessment (GCA): the harder of the two, but manageable with preparation. It's done on CodeSignal , either in person or online. To prepare, practice DSA questions on competitive programming sites like LeetCode , Codewars , and CodeChef for 1–2 weeks, and you should be in good shape. Cognitive Test: taken the same day as the GCA, this evaluates problem-solving, pattern recognition, numerical analysis, and similar skills. Preparation helps here too. Watching a few Y

2026-08-09 原文 →
AI 资讯

Why I stopped guessing at Spark and dbt config values

I've spent more than a decade building data pipelines, and the part nobody warns you about isn't the pipeline logic. It's the tuning. Executor memory, shuffle partitions, cluster size, thread counts. You pick numbers, ship it, and a few weeks later something breaks in a way that's obviously tuning-related but not obviously what to change . The pattern repeats enough times that you start recognizing it before you've even opened the logs. Job's slow, thousands of tiny shuffle tasks, someone way overestimated the partition count. Job dies on OOM, memory's set for last quarter's data volume, nobody updated it since. Cloud bill jumps, a cluster's been sized for peak load and just sits there mostly idle the other 20 hours a day. Every senior data engineer has this pattern-matching running in their head. It's tribal knowledge, and it lives in one or two people's heads on most teams, which means it doesn't scale and it definitely doesn't survive someone leaving. So I built a small tool to make that pattern-matching explicit instead of tribal: it reads your pipeline's config alongside its actual run metrics and tells you what's likely wrong, with the reasoning shown, not just a suggested number. Why rules instead of a model The obvious move in 2026 is to reach for an ML model. I didn't, and it wasn't because I don't think ML has a place here eventually. It's that for this specific problem, a handful of threshold rules already gets you most of the value, and they're something you can actually audit. If a rule fires, I can point at the exact condition and the exact number: average heap usage 28%, peak 47%, five runs, no OOM errors, therefore memory's over-provisioned, shrink it by roughly a fifth. That's checkable. You can look at your own metrics and see whether the reasoning holds. A model's confidence score doesn't give you that, and for something that's about to change a production config, I want the person approving it to be able to say "yes, I see why" rather than "the m

2026-08-09 原文 →
AI 资讯

Building a Bulletproof Comment Reply System in Node.js & MongoDB 🚀

When building a nested reply system, most developers worry about deep tree complexity or messy data structures. For Vlox , I took a different approach: keeping things flat, fast, and secure by reusing a single Mongoose schema with smart atomic limits. Here is a deep dive into how I engineered a production-ready, race-condition-safe reply mechanism using MongoDB transactions, strict type sanitization, and automated limits. How It Works 🛠️ User Action: A user clicks the reply icon and submits their reply. The Payload: Vlox's system sends 3 fields via the endpoint /api/v1/reply/comment/post/:id : id : The post ID (passed as a URL parameter). rootCommentId : The ID of the root comment being replied to. reply : The raw text entered by the user. Sanitization & Validation: The incoming reply is instantly converted to a trimmed string. It then passes through two critical validation checks: Existence Check: The reply must exist. (If a malicious actor sends a payload without a body, the string literally evaluates to "undefined" and gets blocked). Length Limit: The reply must be under 201 characters, enforcing the standard comment limit. Atomic Transactions: If the validation checks pass, the system initiates a Mongoose transaction to execute the following steps safely: Permission Check: It verifies if the user has permission to reply by checking the post's status via await schemas.Posts.findOne(hotQueries.find_user_post(id, req.session.userId)); . Creation: If permissions are valid, it creates a new reply. (Fun fact: It reuses the exact same schema as standard comments!) The Reply Schema Structure: The reply object functions just like a normal comment, with two distinct exceptions: It does not contain a repliesCount field. It includes an extra rootId field, which explicitly points to the ID of the root comment being replied to. Concurrency & Caps: To guarantee that a single comment never receives more than 10 replies while simultaneously incrementing the counter, the system r

2026-08-09 原文 →
AI 资讯

LLM-as-a-Judge: Setting One Up That You Can Trust

Using a model to grade another model’s output is the only approach that scales to open-ended text. It is also the point at which your measurement device becomes a second stochastic system with opinions, and the difference between a useful judge and a number-generator is entirely in whether you validated it. A judge is an instrument, not an oracle Think of the judge the way a lab thinks about a thermometer. It has a reading, a bias, a precision, and a range over which it is trustworthy — and none of those are known until you check it against a reference. The reference is human labels. There is no way around this: a judge whose agreement with humans on your task is unknown produces numbers whose meaning is unknown, however many decimal places the harness prints. The good news is that the calibration is a one-off cost of a few hundred human labels, after which the judge runs for essentially free on every subsequent evaluation. That trade is what makes judges worth the trouble. What the published agreement figures say The standard reference is Zheng et al., 2023, “Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena”. On their setup, a strong judge model agreed with human expert preferences at a rate above 80% — which the authors note is comparable to the agreement rate between two human experts on the same comparisons. That framing is the important part: the ceiling for a judge is not perfect agreement, it is human-human agreement, because the humans disagree with each other on genuinely ambiguous items. The same paper documents the failure modes that come with it — position bias, verbosity bias, self-enhancement bias, and weakness on maths and reasoning items where the judge must itself solve the problem to grade it. So the honest summary of the literature is: a well-constructed judge on general chat quality can approach human-level agreement, and it does so while carrying systematic biases that you have to design around. It is not evidence that your judge, on your

2026-08-08 原文 →
开发者

DBNavigator – An DataGrip-inspired Database IDE Built with JavaFX

After months of development, I'm excited to share DBNavigator, a cross-platform database IDE that I've been building from scratch using Java and JavaFX. ✨ Current Features ✅ PostgreSQL support ✅ MySQL support ✅ Modern Datagrip-inspired UI ✅ Multi-tab SQL editor ✅ Syntax highlighting ✅ Schema explorer ✅ Query execution ✅ Professional dark theme ✅ Cross-platform (Windows, Linux & macOS) This project has been an incredible learning journey in desktop application development, JavaFX UI design, database connectivity, and IDE architecture. I'm sharing it with the developer community because I'd genuinely appreciate your honest feedback. I'd love to hear your thoughts on: UI/UX design Performance Missing features Overall developer experience Architecture and code quality Any bugs or improvements you notice Whether you're a Java developer, DBA, or someone who works with databases every day, your feedback would mean a lot and help shape the next version of the project. ⭐ If you find the project interesting, please consider giving it a star on GitHub. GitHub: DBNavigator Thank you for taking the time to review it. Every suggestion, issue report, and critique is greatly appreciated! 🙌

2026-08-08 原文 →
AI 资讯

Building Autocomplete Like a Jedi: Mastering the Trie

The Quest Begins (The "Why") Honestly, I still remember the first time I tried to build an autocomplete widget for a side‑project. I had a list of 200 k product names, a simple filter that ran on every keystroke, and the UI felt like wading through molasses. Each keypress triggered a full scan of the list, and with a few users typing at once the browser would start to lag. I was stuck in a loop that felt like the infamous “boss fight” where you keep hitting the same pattern over and over, hoping for a different outcome. I kept asking myself: There has to be a smarter way. Why am I re‑checking the same prefixes again and again? If ten users type “tea”, why do I walk through the whole dictionary ten separate times? That question turned into a mini‑quest, and the treasure at the end was the trie data structure. The Revelation (The Insight) Look, the magic of a trie isn’t that it’s some exotic tree; it’s that it stores words by their shared prefixes . Imagine you have the words “cat”, “car”, “cart”, and “dog”. In a trie you’d have a root node, then a c branch that splits into a → t (for “cat”) and a → r → t (for “cart”), while “dog” lives on its own d → o → g path. Every common prefix is stored once , and you can walk down the tree following the characters of a query to land exactly at the node that represents all words with that prefix. Why does this give us O(L + K) time for autocomplete, where L is the length of the prefix and K is the number of results? Walking the trie follows the prefix character‑by‑character → O(L). From that node we just need to collect all words in its subtree. If we keep a list of words at each node (or run a DFS), we touch each result once → O(K). No extra work for words that don’t share the prefix. Contrast that with the naive filter approach: O(N × L) where N is the total dictionary size. For a large N, the trie is a game‑changer—it’s like switching from swinging a blunt sword to wielding a lightsaber that cuts through the prefix forest in

2026-08-07 原文 →
AI 资讯

Which EU countries let you check a company for free: a status table

If you are building anything that touches European business data — onboarding, invoicing, KYB, fraud checks — you will eventually ask the same question I did: which countries can I actually get company data from, for free, without an account? I could not find this written down anywhere, so I worked it out the hard way while building a supplier checker. Here it is. The baseline: VIES The European Commission runs VIES , which validates VAT numbers across all 27 member states plus Northern Ireland ( XI ). It is free, it needs no key, and it is the obvious starting point. Two things about it are worth knowing before you build on it. It answers one question: is this VAT number currently registered. It does not tell you the company is solvent, trading, or that it has not been struck off. A company in liquidation keeps a cleanly resolving VAT number for months, because deregistration and insolvency are run by different authorities on different timetables. Name and address are returned for 25 of the 28 jurisdictions, not all of them. Germany and Spain confirm registration but publish no company name through VIES. I tested three valid numbers for each before accepting that. For those two, a yes/no is genuinely all you can honestly show. Where you can go further, free Ten countries publish enough through a national register to add something meaningful on top of VIES: Country Free register Reports company state Reports VAT-active Romania yes yes yes Poland yes — yes Slovenia yes — yes Estonia yes yes — France yes yes — Greece yes yes — Bulgaria yes yes — Latvia yes yes — Czechia yes — — Finland yes — — Company state means the register tells you whether a business is inactive, in liquidation, bankrupt, insolvent, terminated or struck off. This is the valuable column, and only six countries have it. VAT-active matters more than it sounds. VIES cannot distinguish "this is a real company that is not VAT-registered" from "this number belongs to nobody". Three registers can. Note th

2026-08-07 原文 →
AI 资讯

Why We Built MicroLeague Sports Vol. 3

Why Sports Data Is Harder Than Most People Think Building believable cross-era simulations turned out to be less about the engine and more about the data underneath it. Here is what we learned. MicroLeague Dev Blog, Vol. 3 By Eddie Solar When we started building MicroLeague Sports, I assumed the simulation engine would be the hard part. The vision was ambitious enough to justify that assumption. Let fans ask whether the 1996 Bulls beat the 2017 Warriors. Whether the 1985 Bears could slow down Patrick Mahomes. Which Cowboys team was actually the greatest. Teaching software to play those games across eras felt like the mountain. I was wrong about which mountain it was. The engine is hard, but it is a solvable, bounded kind of hard. The data underneath it is a different animal. Like most developers approaching this for the first time, we figured sports data was largely a collection exercise: gather historical teams, player stats, schedules, and box scores, feed it to the model, done. That assumption fell apart almost immediately, and the reason it fell apart is the subject of this article. Sports data is not a collection problem. It is an identity problem. Franchises do not stay the same thing. Players are not one entity. And the historical record does not agree with itself. The Real Problem Is Modeling Identity Over Time Volume 2 covered the era problem: statistics are confounded by the conditions that produced them, so a raw number pulled across decades lies to you. That is a normalization challenge, and it is real. But normalization assumes you already know what you are normalizing. Before you can compare the 1992 Cowboys to the 2023 Chiefs, your system has to have a confident answer to a more basic question: what exactly is a "team," and what exactly is a "player," when your dataset spans a hundred years? Those sound like trivial questions. They are not. They are the questions that ate most of our early engineering time, and getting them wrong quietly corrupts ever

2026-08-07 原文 →
AI 资讯

I benchmarked my language against Rust and Zig, and deleted my best number

I have been building machin for a while — a Go-flavored, type-inferred language that compiles through C to a single native binary. It has grown a lot recently, and I wanted to answer the obvious question honestly: does it beat Rust and Zig at anything? It does, at two things, decisively. But the first thing I found was not a win. It was my own benchmark quietly lying to me, and the number it was lying about was the best one I had. The benchmark was measuring the order I ran things in machin's repo has had a bench/native-speed suite for months: four compute kernels — recursive fib, a mandelbrot, a sieve, a big integer loop — written in machin, Rust and Zig, producing byte-identical output, so the timing compares the same computation three ways. The published result claimed machin won the integer loop by 20-25% . That claim also shipped inside machin guide , which is what every coding agent reads to learn the language. When I re-ran it, the margin was gone. Not shrunk — gone. So I read the harness instead of the output: for kernel in kernels : for lang in [ machin , rust , zig ]: for _ in range ( 5 ): # all 5 machin, THEN all 5 rust, THEN all 5 zig time ( binary ) It ran every sample of one language before starting the next. On a laptop that heats up and down-clocks during a three-second kernel, that does not measure the languages. It measures who had the misfortune of running last . Zig always went last. Zig always looked slowest. The fix is four lines — interleave the rounds, rotate who starts each one. Here is what my headline number did: intsum 10^9 before (blocked) after (interleaved) machin 2832 ms 3079.7 ms rust 3764 ms 3223.8 ms zig 3556 ms 3189.7 ms "machin +20-25%" machin +3% = a TIE A 20-25% win became a tie. I deleted the claim from the README and from machin guide . The harness now also refuses to declare a winner inside a 3% band, because the worst run-to-run spread I measured was 41% of the min sample. Calling winners inside that is how benchmarks start

2026-08-07 原文 →
AI 资讯

Random Forest Is Horizontal Scaling for Predictions

Classic Machine Learning Through the Eyes of an SRE — Part 3 The random forest is the first ML algorithm that made me feel at home. Not because of the math — because it's an SRE idea wearing a stats costume. Many independent workers. No single point of failure. Majority vote. If one worker goes weird, the fleet absorbs it. We've been building systems this way for decades; the forest just applies it to prediction. The problem it exists to fix Last article: a single decision tree is readable but unstable — small data change, whole tree flips, explanation rewrites itself. That instability is variance, and it's exactly what scared me about trusting one tree in production. The forest's move: grow hundreds of trees, each on a random resample of the data, and — this is the part that matters — force each split to choose from only a random subset of features. That second randomization is the whole difference between a random forest and plain bagging. Bagging alone gives you many trees on resampled data, but if one feature is strongly predictive, every tree grabs it first and they all end up looking alike. Starving each split of features is what makes the trees genuinely different from each other. The randomness isn't sloppiness. It's manufactured disagreement. The instability doesn't get fixed. It gets CANCELLED. Each tree is still jumpy, but they're jumpy in different directions, and the average is calm. What surprised me No new loss function. Each tree still minimizes impurity exactly like a lone tree. The forest adds zero new objectives. The entire gain is a bias-variance bargain: variance drops hard, bias barely moves. You give up readability and get back trustworthiness. Embarrassingly parallel. Trees are independent, so training scales horizontally — throw cores at it. Boosting, its sequential cousin, is the opposite: each model depends on the last. Map-reduce versus a pipeline. The smoothness illusion. A forest's decision boundary looks smooth, almost like regression'

2026-08-07 原文 →
AI 资讯

How to Detect Overtraining Before It Hits: Analyzing HRV with Python and Isolation Forests 🏃‍♂️📉

We’ve all been there: you're crushing your workouts, feeling like a beast, and then suddenly— bam . You can’t get out of bed, your resting heart rate is through the roof, and your motivation has evaporated. Welcome to Overtraining Syndrome (OTS) . In the world of sports science, Heart Rate Variability (HRV) is the gold standard for tracking recovery. By analyzing the tiny fluctuations between heartbeats (R-R intervals), we can peek into our Autonomic Nervous System (ANS). Today, we’re going to build a Python-based pipeline to fetch data from the Oura Cloud API , calculate key HRV metrics like SDNN and RMSSD , and use an Isolation Forest model to detect when you're pushing a bit too hard. Whether you're a biohacker or a developer interested in wearable data analysis , this guide will show you how to turn raw health data into actionable recovery insights. The Architecture: From Pulse to Prediction 🏗️ Before we dive into the code, let's visualize how the data flows from your finger to our anomaly detection model. graph TD A[Oura Ring] -->|Sync| B(Oura Cloud API) B -->|Raw R-R Intervals| C{Data Preprocessing} C -->|Filtering Artifacts| D[Feature Extraction] D -->|SDNN & RMSSD| E[Isolation Forest Model] E -->|Normal| F[Keep Training! 🚀] E -->|Anomaly| G[Rest Day Required! 🛑] Prerequisites 🛠️ To follow along, you’ll need a few tools in your tech_stack : Python 3.9+ Scikit-learn : For our machine learning magic. SciPy/NumPy : For the heavy math lifting. Oura Cloud API Access : To get that sweet, sweet biometric data. pip install scikit-learn scipy pandas requests Step 1: Fetching R-R Intervals from Oura 💍 The Oura Ring records "R-R intervals" (the time between successive heartbeats in milliseconds) during sleep. This is much more granular than a simple "Heart Rate" average. import requests import pandas as pd def fetch_oura_hrv_data ( api_token , start_date , end_date ): url = f ' https://api.ouraring.com/v2/usercollection/heart_rate ' headers = { ' Authorization ' : f ' B

2026-08-07 原文 →
AI 资讯

Three Ways Your Training Data Lies to You (And None of Them Throw an Error)

Every failure I am about to describe produced a clean run. No exception, no stack trace, no red build. Each one produced a plausible number that I believed for longer than I should have. That is the category of bug I have come to fear most. A crash tells you it crashed. A silently broken dataset tells you nothing at all, and your metrics will politely agree with it. Here are three from the last year, all from my own work, all found late. 1. The dataset that was 92% one category I had a training set of 688 records for a multi-category vision-language task. Thirteen categories. Reasonable size for a fine-tune, already used in a completed training run whose results I had written up. While preparing a stratified split, I joined the records back against the source annotations and actually counted the categories. 630 of 688 were a single category: scene captions. Zero examples of traffic signals. Zero of planning. Zero of uncertainty. Several categories the evaluation explicitly measured had no representation in training at all. The previous fine-tune had shown gains on some of those very categories. I had interpreted this as the model learning the task. The real explanation was duller and more useful: the model had learned the answer format from caption supervision, and format alignment alone was enough to move a multiple-choice score. Nothing category-specific had been learned, because nothing category-specific had been shown. The root cause was upstream and boring. The conversion script I inherited only rewrote file paths and dropped records with missing frames. It faithfully preserved a caption-only selection made further up the chain. It had no opinion about balance because nobody had asked it to have one. What I changed: the composition of a training set is now an artifact I generate and inspect before any run, not a property I assume. A category histogram takes seconds. I had not looked, for months. 2. The 18-hour run that converged perfectly to nothing Large model

2026-08-07 原文 →